19f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff/*
29f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff * Copyright (C) 2009 The Android Open Source Project
39f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff *
49f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff * Licensed under the Apache License, Version 2.0 (the "License");
59f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff * you may not use this file except in compliance with the License.
69f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff * You may obtain a copy of the License at
79f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff *
89f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff *      http://www.apache.org/licenses/LICENSE-2.0
99f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff *
109f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff * Unless required by applicable law or agreed to in writing, software
119f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff * distributed under the License is distributed on an "AS IS" BASIS,
129f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff * See the License for the specific language governing permissions and
149f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff * limitations under the License
159f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff */
169f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
179f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriffpackage com.android.providers.calendar;
189f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
199f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriffimport android.accounts.Account;
209f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriffimport android.content.ContentResolver;
219f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriffimport android.content.ContentValues;
229f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriffimport android.content.Context;
239f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriffimport android.database.Cursor;
249f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriffimport android.database.DatabaseUtils;
250d8699eedb0f3bcec1854b9753ae59154a122726Michael Chanimport android.database.SQLException;
269f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriffimport android.database.sqlite.SQLiteDatabase;
27a6357118c223d00ed722ecd40ecdda92d705d211Erikimport android.database.sqlite.SQLiteException;
289f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriffimport android.database.sqlite.SQLiteOpenHelper;
299f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriffimport android.os.Bundle;
30b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErikimport android.provider.CalendarContract;
31b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErikimport android.provider.CalendarContract.Attendees;
322f251c778c06d21ed7693a70f4a1268ff929242eRoboErikimport android.provider.CalendarContract.Calendars;
332f251c778c06d21ed7693a70f4a1268ff929242eRoboErikimport android.provider.CalendarContract.Colors;
34b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErikimport android.provider.CalendarContract.Events;
35b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErikimport android.provider.CalendarContract.Reminders;
36d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriffimport android.provider.SyncStateContract;
377b40dde3168f4af2c757cb43955aa3bfe1668666Erikimport android.text.TextUtils;
38ae4f20e120d3107cef20be860a612c9c23816295Erikimport android.text.format.Time;
399f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriffimport android.util.Log;
409f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
41b2695bf3cfb173c4c5ba7bfd3c93ba8a51d65810Alon Albertimport com.android.common.content.SyncStateContentProviderHelper;
42b2695bf3cfb173c4c5ba7bfd3c93ba8a51d65810Alon Albertimport com.google.common.annotations.VisibleForTesting;
43b2695bf3cfb173c4c5ba7bfd3c93ba8a51d65810Alon Albert
44d39cfe09aa7e752cdc7512ae58d90d49d4b5ef9eKen Shirriffimport java.io.UnsupportedEncodingException;
45162c7c9bbd53b623fbe913b376e7f7f42915bb59Marc Blankimport java.net.URLDecoder;
46315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglioimport java.util.TimeZone;
47d39cfe09aa7e752cdc7512ae58d90d49d4b5ef9eKen Shirriff
489f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff/**
499f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff * Database helper for calendar. Designed as a singleton to make sure that all
509f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff * {@link android.content.ContentProvider} users get the same reference.
519f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff */
529f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff/* package */ class CalendarDatabaseHelper extends SQLiteOpenHelper {
5381d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang
549f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private static final String TAG = "CalendarDatabaseHelper";
559f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
5681d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang    private static final boolean LOGD = false;
5781d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang
58c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan    @VisibleForTesting
59c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan    public boolean mInTestMode = false;
60c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan
61ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff    private static final String DATABASE_NAME = "calendar.db";
629f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
637b40dde3168f4af2c757cb43955aa3bfe1668666Erik    private static final int DAY_IN_SECONDS = 24 * 60 * 60;
647b40dde3168f4af2c757cb43955aa3bfe1668666Erik
659f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    // Note: if you update the version number, you must also update the code
669f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    // in upgradeDatabase() to modify the database (gracefully, if possible).
670d8699eedb0f3bcec1854b9753ae59154a122726Michael Chan    //
680d8699eedb0f3bcec1854b9753ae59154a122726Michael Chan    //  xx Froyo and prior
690d8699eedb0f3bcec1854b9753ae59154a122726Michael Chan    // 1xx for Gingerbread,
700d8699eedb0f3bcec1854b9753ae59154a122726Michael Chan    // 2xx for Honeycomb
710d8699eedb0f3bcec1854b9753ae59154a122726Michael Chan    // 3xx for ICS
720d8699eedb0f3bcec1854b9753ae59154a122726Michael Chan    // 4xx for JB
73b2695bf3cfb173c4c5ba7bfd3c93ba8a51d65810Alon Albert    // 5xx for JB MR1
74b2695bf3cfb173c4c5ba7bfd3c93ba8a51d65810Alon Albert    // 6xx for K
750d8699eedb0f3bcec1854b9753ae59154a122726Michael Chan    // Bump this to the next hundred at each major release.
767a2531a4b68e9efe14353cc7f4a64a8c5613e5d3Alon Albert    static final int DATABASE_VERSION = 600;
779f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
78d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff    private static final int PRE_FROYO_SYNC_STATE_VERSION = 3;
79d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff
809ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert    // columns used to duplicate an event row
8102f97c538fc46a08d857d2c807c76fd0eec12493RoboErik    private static final String LAST_SYNCED_EVENT_COLUMNS =
8202f97c538fc46a08d857d2c807c76fd0eec12493RoboErik            Events._SYNC_ID + "," +
8302f97c538fc46a08d857d2c807c76fd0eec12493RoboErik            Events.CALENDAR_ID + "," +
8402f97c538fc46a08d857d2c807c76fd0eec12493RoboErik            Events.TITLE + "," +
8502f97c538fc46a08d857d2c807c76fd0eec12493RoboErik            Events.EVENT_LOCATION + "," +
8602f97c538fc46a08d857d2c807c76fd0eec12493RoboErik            Events.DESCRIPTION + "," +
8702f97c538fc46a08d857d2c807c76fd0eec12493RoboErik            Events.EVENT_COLOR + "," +
88387535fec9f646e0b7acb82d5354f2b5ebee4395RoboErik            Events.EVENT_COLOR_KEY + "," +
8902f97c538fc46a08d857d2c807c76fd0eec12493RoboErik            Events.STATUS + "," +
9002f97c538fc46a08d857d2c807c76fd0eec12493RoboErik            Events.SELF_ATTENDEE_STATUS + "," +
9102f97c538fc46a08d857d2c807c76fd0eec12493RoboErik            Events.DTSTART + "," +
9202f97c538fc46a08d857d2c807c76fd0eec12493RoboErik            Events.DTEND + "," +
9302f97c538fc46a08d857d2c807c76fd0eec12493RoboErik            Events.EVENT_TIMEZONE + "," +
9402f97c538fc46a08d857d2c807c76fd0eec12493RoboErik            Events.EVENT_END_TIMEZONE + "," +
9502f97c538fc46a08d857d2c807c76fd0eec12493RoboErik            Events.DURATION + "," +
9602f97c538fc46a08d857d2c807c76fd0eec12493RoboErik            Events.ALL_DAY + "," +
9702f97c538fc46a08d857d2c807c76fd0eec12493RoboErik            Events.ACCESS_LEVEL + "," +
9802f97c538fc46a08d857d2c807c76fd0eec12493RoboErik            Events.AVAILABILITY + "," +
9902f97c538fc46a08d857d2c807c76fd0eec12493RoboErik            Events.HAS_ALARM + "," +
10002f97c538fc46a08d857d2c807c76fd0eec12493RoboErik            Events.HAS_EXTENDED_PROPERTIES + "," +
10102f97c538fc46a08d857d2c807c76fd0eec12493RoboErik            Events.RRULE + "," +
10202f97c538fc46a08d857d2c807c76fd0eec12493RoboErik            Events.RDATE + "," +
10302f97c538fc46a08d857d2c807c76fd0eec12493RoboErik            Events.EXRULE + "," +
10402f97c538fc46a08d857d2c807c76fd0eec12493RoboErik            Events.EXDATE + "," +
10502f97c538fc46a08d857d2c807c76fd0eec12493RoboErik            Events.ORIGINAL_SYNC_ID + "," +
10602f97c538fc46a08d857d2c807c76fd0eec12493RoboErik            Events.ORIGINAL_ID + "," +
10702f97c538fc46a08d857d2c807c76fd0eec12493RoboErik            Events.ORIGINAL_INSTANCE_TIME + "," +
10802f97c538fc46a08d857d2c807c76fd0eec12493RoboErik            Events.ORIGINAL_ALL_DAY + "," +
10902f97c538fc46a08d857d2c807c76fd0eec12493RoboErik            Events.LAST_DATE + "," +
11002f97c538fc46a08d857d2c807c76fd0eec12493RoboErik            Events.HAS_ATTENDEE_DATA + "," +
11102f97c538fc46a08d857d2c807c76fd0eec12493RoboErik            Events.GUESTS_CAN_MODIFY + "," +
11202f97c538fc46a08d857d2c807c76fd0eec12493RoboErik            Events.GUESTS_CAN_INVITE_OTHERS + "," +
11302f97c538fc46a08d857d2c807c76fd0eec12493RoboErik            Events.GUESTS_CAN_SEE_GUESTS + "," +
114c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan            Events.ORGANIZER + "," +
115b2695bf3cfb173c4c5ba7bfd3c93ba8a51d65810Alon Albert            Events.IS_ORGANIZER + "," +
116c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan            Events.CUSTOM_APP_PACKAGE + "," +
117501e60bcb1b519d80723f7b64ba60bd079b8ec8dSara Ting            Events.CUSTOM_APP_URI + "," +
118501e60bcb1b519d80723f7b64ba60bd079b8ec8dSara Ting            Events.UID_2445;
1199ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert
1209ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert    // columns used to duplicate a reminder row
12102f97c538fc46a08d857d2c807c76fd0eec12493RoboErik    private static final String LAST_SYNCED_REMINDER_COLUMNS =
122470aa5bc291ca33d51dda356f38ac2954026da9aAlon Albert            Reminders.MINUTES + "," +
123470aa5bc291ca33d51dda356f38ac2954026da9aAlon Albert            Reminders.METHOD;
1249ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert
1259ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert    // columns used to duplicate an attendee row
12602f97c538fc46a08d857d2c807c76fd0eec12493RoboErik    private static final String LAST_SYNCED_ATTENDEE_COLUMNS =
127470aa5bc291ca33d51dda356f38ac2954026da9aAlon Albert            Attendees.ATTENDEE_NAME + "," +
128470aa5bc291ca33d51dda356f38ac2954026da9aAlon Albert            Attendees.ATTENDEE_EMAIL + "," +
129470aa5bc291ca33d51dda356f38ac2954026da9aAlon Albert            Attendees.ATTENDEE_STATUS + "," +
130470aa5bc291ca33d51dda356f38ac2954026da9aAlon Albert            Attendees.ATTENDEE_RELATIONSHIP + "," +
131bafe9de156292f65b1079dd1eb586669f573d9e6Michael Chan            Attendees.ATTENDEE_TYPE + "," +
132bafe9de156292f65b1079dd1eb586669f573d9e6Michael Chan            Attendees.ATTENDEE_IDENTITY + "," +
133bafe9de156292f65b1079dd1eb586669f573d9e6Michael Chan            Attendees.ATTENDEE_ID_NAMESPACE;
1349ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert
1359ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert    // columns used to duplicate an extended property row
13602f97c538fc46a08d857d2c807c76fd0eec12493RoboErik    private static final String LAST_SYNCED_EXTENDED_PROPERTY_COLUMNS =
137b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik            CalendarContract.ExtendedProperties.NAME + "," +
138b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik            CalendarContract.ExtendedProperties.VALUE;
1399ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert
1407cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio    public interface Tables {
1417cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio        public static final String CALENDARS = "Calendars";
1427cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio        public static final String EVENTS = "Events";
1437cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio        public static final String EVENTS_RAW_TIMES = "EventsRawTimes";
1447cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio        public static final String INSTANCES = "Instances";
1457cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio        public static final String ATTENDEES = "Attendees";
1467cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio        public static final String REMINDERS = "Reminders";
1477cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio        public static final String CALENDAR_ALERTS = "CalendarAlerts";
1487cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio        public static final String EXTENDED_PROPERTIES = "ExtendedProperties";
1497cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio        public static final String CALENDAR_META_DATA = "CalendarMetaData";
1507cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio        public static final String CALENDAR_CACHE = "CalendarCache";
1517cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio        public static final String SYNC_STATE = "_sync_state";
1527cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio        public static final String SYNC_STATE_META = "_sync_state_metadata";
1532f251c778c06d21ed7693a70f4a1268ff929242eRoboErik        public static final String COLORS = "Colors";
1547cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio    }
1557cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio
1567cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio    public interface Views {
157bcba82631ab0ee16efe58f0e0b0b9c18d93a6fd2Andy McFadden        public static final String EVENTS = "view_events";
1587cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio    }
1597cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio
160d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff    // Copied from SyncStateContentProviderHelper.  Don't really want to make them public there.
161d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff    private static final String SYNC_STATE_META_VERSION_COLUMN = "version";
162d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff
1637cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio    // This needs to be done when all the tables are already created
1647cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio    private static final String EVENTS_CLEANUP_TRIGGER_SQL =
1657cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio            "DELETE FROM " + Tables.INSTANCES +
166b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                " WHERE "+ CalendarContract.Instances.EVENT_ID + "=" +
167b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                    "old." + CalendarContract.Events._ID + ";" +
1687cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio            "DELETE FROM " + Tables.EVENTS_RAW_TIMES +
169b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                " WHERE " + CalendarContract.EventsRawTimes.EVENT_ID + "=" +
170b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                    "old." + CalendarContract.Events._ID + ";" +
1717cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio            "DELETE FROM " + Tables.ATTENDEES +
172b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                " WHERE " + CalendarContract.Attendees.EVENT_ID + "=" +
173b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                    "old." + CalendarContract.Events._ID + ";" +
1747cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio            "DELETE FROM " + Tables.REMINDERS +
175b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                " WHERE " + CalendarContract.Reminders.EVENT_ID + "=" +
176b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                    "old." + CalendarContract.Events._ID + ";" +
1777cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio            "DELETE FROM " + Tables.CALENDAR_ALERTS +
178b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                " WHERE " + CalendarContract.CalendarAlerts.EVENT_ID + "=" +
179b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                    "old." + CalendarContract.Events._ID + ";" +
1807cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio            "DELETE FROM " + Tables.EXTENDED_PROPERTIES +
181b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                " WHERE " + CalendarContract.ExtendedProperties.EVENT_ID + "=" +
182b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                    "old." + CalendarContract.Events._ID + ";";
1837cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio
18434c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik    // This ensures any exceptions based on an event get their original_sync_id
18534c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik    // column set when an the _sync_id is set.
18634c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik    private static final String EVENTS_ORIGINAL_SYNC_TRIGGER_SQL =
18734c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik            "UPDATE " + Tables.EVENTS +
18834c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik                " SET " + Events.ORIGINAL_SYNC_ID + "=new." + Events._SYNC_ID +
18934c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik                " WHERE " + Events.ORIGINAL_ID + "=old." + Events._ID + ";";
19034c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik
19134c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik    private static final String SYNC_ID_UPDATE_TRIGGER_NAME = "original_sync_update";
19234c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik    private static final String CREATE_SYNC_ID_UPDATE_TRIGGER =
19334c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik            "CREATE TRIGGER " + SYNC_ID_UPDATE_TRIGGER_NAME + " UPDATE OF " + Events._SYNC_ID +
19434c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik            " ON " + Tables.EVENTS +
19534c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik            " BEGIN " +
19634c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik                EVENTS_ORIGINAL_SYNC_TRIGGER_SQL +
19734c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik            " END";
19834c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik
1997cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio    private static final String CALENDAR_CLEANUP_TRIGGER_SQL = "DELETE FROM " + Tables.EVENTS +
200b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik            " WHERE " + CalendarContract.Events.CALENDAR_ID + "=" +
201b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                "old." + CalendarContract.Events._ID + ";";
2027cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio
2032f251c778c06d21ed7693a70f4a1268ff929242eRoboErik    private static final String CALENDAR_UPDATE_COLOR_TRIGGER_SQL = "UPDATE " + Tables.CALENDARS
2042f251c778c06d21ed7693a70f4a1268ff929242eRoboErik            + " SET calendar_color=(SELECT " + Colors.COLOR + " FROM " + Tables.COLORS + " WHERE "
2052f251c778c06d21ed7693a70f4a1268ff929242eRoboErik            + Colors.ACCOUNT_NAME + "=" + "new." + Calendars.ACCOUNT_NAME + " AND "
2062f251c778c06d21ed7693a70f4a1268ff929242eRoboErik            + Colors.ACCOUNT_TYPE + "=" + "new." + Calendars.ACCOUNT_TYPE + " AND "
207c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert            + Colors.COLOR_KEY + "=" + "new." + Calendars.CALENDAR_COLOR_KEY + " AND "
208c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert            + Colors.COLOR_TYPE + "=" + Colors.TYPE_CALENDAR + ") "
2092f251c778c06d21ed7693a70f4a1268ff929242eRoboErik            + " WHERE " + Calendars._ID + "=" + "old." + Calendars._ID
2102f251c778c06d21ed7693a70f4a1268ff929242eRoboErik            + ";";
2112f251c778c06d21ed7693a70f4a1268ff929242eRoboErik    private static final String CALENDAR_COLOR_UPDATE_TRIGGER_NAME = "calendar_color_update";
2122f251c778c06d21ed7693a70f4a1268ff929242eRoboErik    private static final String CREATE_CALENDAR_COLOR_UPDATE_TRIGGER = "CREATE TRIGGER "
213387535fec9f646e0b7acb82d5354f2b5ebee4395RoboErik            + CALENDAR_COLOR_UPDATE_TRIGGER_NAME + " UPDATE OF " + Calendars.CALENDAR_COLOR_KEY
214387535fec9f646e0b7acb82d5354f2b5ebee4395RoboErik            + " ON " + Tables.CALENDARS + " WHEN new." + Calendars.CALENDAR_COLOR_KEY
2152f251c778c06d21ed7693a70f4a1268ff929242eRoboErik            + " NOT NULL BEGIN " + CALENDAR_UPDATE_COLOR_TRIGGER_SQL + " END";
2162f251c778c06d21ed7693a70f4a1268ff929242eRoboErik
2172f251c778c06d21ed7693a70f4a1268ff929242eRoboErik    private static final String EVENT_UPDATE_COLOR_TRIGGER_SQL = "UPDATE " + Tables.EVENTS
2182f251c778c06d21ed7693a70f4a1268ff929242eRoboErik            + " SET eventColor=(SELECT " + Colors.COLOR + " FROM " + Tables.COLORS + " WHERE "
2192f251c778c06d21ed7693a70f4a1268ff929242eRoboErik            + Colors.ACCOUNT_NAME + "=" + "(SELECT " + Calendars.ACCOUNT_NAME + " FROM "
2202f251c778c06d21ed7693a70f4a1268ff929242eRoboErik            + Tables.CALENDARS + " WHERE " + Calendars._ID + "=new." + Events.CALENDAR_ID
2212f251c778c06d21ed7693a70f4a1268ff929242eRoboErik            + ") AND " + Colors.ACCOUNT_TYPE + "=" + "(SELECT " + Calendars.ACCOUNT_TYPE + " FROM "
2222f251c778c06d21ed7693a70f4a1268ff929242eRoboErik            + Tables.CALENDARS + " WHERE " + Calendars._ID + "=new." + Events.CALENDAR_ID
223c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert            + ") AND " + Colors.COLOR_KEY + "=" + "new." + Events.EVENT_COLOR_KEY + " AND "
224c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert            + Colors.COLOR_TYPE + "=" + Colors.TYPE_EVENT + ") "
2252f251c778c06d21ed7693a70f4a1268ff929242eRoboErik            + " WHERE " + Events._ID + "=" + "old." + Events._ID + ";";
2262f251c778c06d21ed7693a70f4a1268ff929242eRoboErik    private static final String EVENT_COLOR_UPDATE_TRIGGER_NAME = "event_color_update";
2272f251c778c06d21ed7693a70f4a1268ff929242eRoboErik    private static final String CREATE_EVENT_COLOR_UPDATE_TRIGGER = "CREATE TRIGGER "
228387535fec9f646e0b7acb82d5354f2b5ebee4395RoboErik            + EVENT_COLOR_UPDATE_TRIGGER_NAME + " UPDATE OF " + Events.EVENT_COLOR_KEY + " ON "
229387535fec9f646e0b7acb82d5354f2b5ebee4395RoboErik            + Tables.EVENTS + " WHEN new." + Events.EVENT_COLOR_KEY + " NOT NULL BEGIN "
2302f251c778c06d21ed7693a70f4a1268ff929242eRoboErik            + EVENT_UPDATE_COLOR_TRIGGER_SQL + " END";
2312f251c778c06d21ed7693a70f4a1268ff929242eRoboErik
232935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden    /** Selects rows from Attendees for which the event_id refers to a nonexistent Event */
233935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden    private static final String WHERE_ATTENDEES_ORPHANS =
234935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            Attendees.EVENT_ID + " IN (SELECT " + Attendees.EVENT_ID + " FROM " +
235935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            Tables.ATTENDEES + " LEFT OUTER JOIN " + Tables.EVENTS + " ON " +
236935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            Attendees.EVENT_ID + "=" + Tables.EVENTS + "." + Events._ID +
237935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            " WHERE " + Tables.EVENTS + "." + Events._ID + " IS NULL)";
238935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden    /** Selects rows from Reminders for which the event_id refers to a nonexistent Event */
239935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden    private static final String WHERE_REMINDERS_ORPHANS =
240935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            Reminders.EVENT_ID + " IN (SELECT " + Reminders.EVENT_ID + " FROM " +
241935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            Tables.REMINDERS + " LEFT OUTER JOIN " + Tables.EVENTS + " ON " +
242935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            Reminders.EVENT_ID + "=" + Tables.EVENTS + "." + Events._ID +
243935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            " WHERE " + Tables.EVENTS + "." + Events._ID + " IS NULL)";
244935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden
2451b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio    private static final String SCHEMA_HTTPS = "https://";
2461b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio    private static final String SCHEMA_HTTP = "http://";
2471b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio
2489f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private final SyncStateContentProviderHelper mSyncState;
2499f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
2509f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private static CalendarDatabaseHelper sSingleton = null;
2519f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
2529f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private DatabaseUtils.InsertHelper mCalendarsInserter;
2532f251c778c06d21ed7693a70f4a1268ff929242eRoboErik    private DatabaseUtils.InsertHelper mColorsInserter;
2549f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private DatabaseUtils.InsertHelper mEventsInserter;
2559f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private DatabaseUtils.InsertHelper mEventsRawTimesInserter;
2569f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private DatabaseUtils.InsertHelper mInstancesInserter;
2579f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private DatabaseUtils.InsertHelper mAttendeesInserter;
2589f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private DatabaseUtils.InsertHelper mRemindersInserter;
2599f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private DatabaseUtils.InsertHelper mCalendarAlertsInserter;
2609f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private DatabaseUtils.InsertHelper mExtendedPropertiesInserter;
2619f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
2629f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    public long calendarsInsert(ContentValues values) {
2639f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        return mCalendarsInserter.insert(values);
2649f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
2659f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
2662f251c778c06d21ed7693a70f4a1268ff929242eRoboErik    public long colorsInsert(ContentValues values) {
2672f251c778c06d21ed7693a70f4a1268ff929242eRoboErik        return mColorsInserter.insert(values);
2682f251c778c06d21ed7693a70f4a1268ff929242eRoboErik    }
2692f251c778c06d21ed7693a70f4a1268ff929242eRoboErik
2709f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    public long eventsInsert(ContentValues values) {
2719f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        return mEventsInserter.insert(values);
2729f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
2739f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
2749f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    public long eventsRawTimesInsert(ContentValues values) {
2759f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        return mEventsRawTimesInserter.insert(values);
2769f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
2779f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
2789f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    public long eventsRawTimesReplace(ContentValues values) {
2799f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        return mEventsRawTimesInserter.replace(values);
2809f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
2819f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
2829f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    public long instancesInsert(ContentValues values) {
2839f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        return mInstancesInserter.insert(values);
2849f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
2859f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
286c874ed5c6cc0fcc6ac06ae7d20db0eab7d749608Ken Shirriff    public long instancesReplace(ContentValues values) {
287c874ed5c6cc0fcc6ac06ae7d20db0eab7d749608Ken Shirriff        return mInstancesInserter.replace(values);
288c874ed5c6cc0fcc6ac06ae7d20db0eab7d749608Ken Shirriff    }
289c874ed5c6cc0fcc6ac06ae7d20db0eab7d749608Ken Shirriff
2909f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    public long attendeesInsert(ContentValues values) {
2919f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        return mAttendeesInserter.insert(values);
2929f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
2939f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
2949f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    public long remindersInsert(ContentValues values) {
2959f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        return mRemindersInserter.insert(values);
2969f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
2979f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
2989f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    public long calendarAlertsInsert(ContentValues values) {
2999f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        return mCalendarAlertsInserter.insert(values);
3009f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
3019f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
3029f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    public long extendedPropertiesInsert(ContentValues values) {
3039f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        return mExtendedPropertiesInserter.insert(values);
3049f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
3059f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
3069f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    public static synchronized CalendarDatabaseHelper getInstance(Context context) {
3079f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        if (sSingleton == null) {
3089f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            sSingleton = new CalendarDatabaseHelper(context);
3099f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
3109f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        return sSingleton;
3119f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
3129f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
3139f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    /**
3149f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * Private constructor, callers except unit tests should obtain an instance through
3159f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * {@link #getInstance(android.content.Context)} instead.
3169f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     */
3177e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff    /* package */ CalendarDatabaseHelper(Context context) {
3189f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        super(context, DATABASE_NAME, null, DATABASE_VERSION);
31981d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        if (LOGD) Log.d(TAG, "Creating OpenHelper");
3209f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
3219f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        mSyncState = new SyncStateContentProviderHelper();
3229f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
3239f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
3249f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    @Override
3259f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    public void onOpen(SQLiteDatabase db) {
3269f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        mSyncState.onDatabaseOpened(db);
3279f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
3287cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio        mCalendarsInserter = new DatabaseUtils.InsertHelper(db, Tables.CALENDARS);
3292f251c778c06d21ed7693a70f4a1268ff929242eRoboErik        mColorsInserter = new DatabaseUtils.InsertHelper(db, Tables.COLORS);
3307cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio        mEventsInserter = new DatabaseUtils.InsertHelper(db, Tables.EVENTS);
3317cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio        mEventsRawTimesInserter = new DatabaseUtils.InsertHelper(db, Tables.EVENTS_RAW_TIMES);
3327cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio        mInstancesInserter = new DatabaseUtils.InsertHelper(db, Tables.INSTANCES);
3337cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio        mAttendeesInserter = new DatabaseUtils.InsertHelper(db, Tables.ATTENDEES);
3347cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio        mRemindersInserter = new DatabaseUtils.InsertHelper(db, Tables.REMINDERS);
3357cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio        mCalendarAlertsInserter = new DatabaseUtils.InsertHelper(db, Tables.CALENDAR_ALERTS);
3369f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        mExtendedPropertiesInserter =
3377cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                new DatabaseUtils.InsertHelper(db, Tables.EXTENDED_PROPERTIES);
3389f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
3399f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
340d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff    /*
341d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff     * Upgrade sync state table if necessary.  Note that the data bundle
342d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff     * in the table is not upgraded.
343d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff     *
344d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff     * The sync state used to be stored with version 3, but now uses the
345d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff     * same sync state code as contacts, which is version 1.  This code
346d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff     * upgrades from 3 to 1 if necessary.  (Yes, the numbers are unfortunately
347d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff     * backwards.)
348d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff     *
349d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff     * This code is only called when upgrading from an old calendar version,
350d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff     * so there is no problem if sync state version 3 gets used again in the
351d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff     * future.
352d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff     */
353d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff    private void upgradeSyncState(SQLiteDatabase db) {
354d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff        long version = DatabaseUtils.longForQuery(db,
355d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff                 "SELECT " + SYNC_STATE_META_VERSION_COLUMN
3567cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                 + " FROM " + Tables.SYNC_STATE_META,
357d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff                 null);
358d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff        if (version == PRE_FROYO_SYNC_STATE_VERSION) {
359d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff            Log.i(TAG, "Upgrading calendar sync state table");
360d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff            db.execSQL("CREATE TEMPORARY TABLE state_backup(_sync_account TEXT, "
361d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff                    + "_sync_account_type TEXT, data TEXT);");
362d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff            db.execSQL("INSERT INTO state_backup SELECT _sync_account, _sync_account_type, data"
363d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff                    + " FROM "
3647cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                    + Tables.SYNC_STATE
365d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff                    + " WHERE _sync_account is not NULL and _sync_account_type is not NULL;");
3667cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio            db.execSQL("DROP TABLE " + Tables.SYNC_STATE + ";");
367d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff            mSyncState.onDatabaseOpened(db);
3687cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio            db.execSQL("INSERT INTO " + Tables.SYNC_STATE + "("
369d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff                    + SyncStateContract.Columns.ACCOUNT_NAME + ","
370d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff                    + SyncStateContract.Columns.ACCOUNT_TYPE + ","
371d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff                    + SyncStateContract.Columns.DATA
372d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff                    + ") SELECT _sync_account, _sync_account_type, data from state_backup;");
373d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff            db.execSQL("DROP TABLE state_backup;");
374d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff        } else {
375d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff            // Wrong version to upgrade.
376d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff            // Don't need to do anything more here because mSyncState.onDatabaseOpened() will blow
377d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff            // away and recreate  the database (which will result in a resync).
378d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff            Log.w(TAG, "upgradeSyncState: current version is " + version + ", skipping upgrade.");
379d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff        }
380d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff    }
381d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff
3829f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    @Override
3839f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    public void onCreate(SQLiteDatabase db) {
384a6357118c223d00ed722ecd40ecdda92d705d211Erik        bootstrapDB(db);
385a6357118c223d00ed722ecd40ecdda92d705d211Erik    }
386a6357118c223d00ed722ecd40ecdda92d705d211Erik
387a6357118c223d00ed722ecd40ecdda92d705d211Erik    private void bootstrapDB(SQLiteDatabase db) {
3889f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        Log.i(TAG, "Bootstrapping database");
3899f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
3909f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        mSyncState.createDatabase(db);
3919f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
3922f251c778c06d21ed7693a70f4a1268ff929242eRoboErik        createColorsTable(db);
3932f251c778c06d21ed7693a70f4a1268ff929242eRoboErik
3941b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio        createCalendarsTable(db);
3959f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
396c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik        createEventsTable(db);
3979f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
3987cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio        db.execSQL("CREATE TABLE " + Tables.EVENTS_RAW_TIMES + " (" +
399b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.EventsRawTimes._ID + " INTEGER PRIMARY KEY," +
400b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.EventsRawTimes.EVENT_ID + " INTEGER NOT NULL," +
401b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.EventsRawTimes.DTSTART_2445 + " TEXT," +
402b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.EventsRawTimes.DTEND_2445 + " TEXT," +
403b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.EventsRawTimes.ORIGINAL_INSTANCE_TIME_2445 + " TEXT," +
404b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.EventsRawTimes.LAST_DATE_2445 + " TEXT," +
405b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                "UNIQUE (" + CalendarContract.EventsRawTimes.EVENT_ID + ")" +
4069f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                ");");
4079f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
4087cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio        db.execSQL("CREATE TABLE " + Tables.INSTANCES + " (" +
409b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Instances._ID + " INTEGER PRIMARY KEY," +
410b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Instances.EVENT_ID + " INTEGER," +
411b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Instances.BEGIN + " INTEGER," +         // UTC millis
412b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Instances.END + " INTEGER," +           // UTC millis
413b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Instances.START_DAY + " INTEGER," +      // Julian start day
414b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Instances.END_DAY + " INTEGER," +        // Julian end day
415b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Instances.START_MINUTE + " INTEGER," +   // minutes from midnight
416b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Instances.END_MINUTE + " INTEGER," +     // minutes from midnight
4177cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                "UNIQUE (" +
418b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                    CalendarContract.Instances.EVENT_ID + ", " +
419b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                    CalendarContract.Instances.BEGIN + ", " +
420b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                    CalendarContract.Instances.END + ")" +
4219f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                ");");
4229f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
4237cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio        db.execSQL("CREATE INDEX instancesStartDayIndex ON " + Tables.INSTANCES + " (" +
424b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Instances.START_DAY +
4259f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                ");");
4269f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
4271599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio        createCalendarMetaDataTable(db);
4289f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
429315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        createCalendarCacheTable(db, null);
430ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio
4317cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio        db.execSQL("CREATE TABLE " + Tables.ATTENDEES + " (" +
432b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Attendees._ID + " INTEGER PRIMARY KEY," +
433b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Attendees.EVENT_ID + " INTEGER," +
434b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Attendees.ATTENDEE_NAME + " TEXT," +
435b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Attendees.ATTENDEE_EMAIL + " TEXT," +
436b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Attendees.ATTENDEE_STATUS + " INTEGER," +
437b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Attendees.ATTENDEE_RELATIONSHIP + " INTEGER," +
438bafe9de156292f65b1079dd1eb586669f573d9e6Michael Chan                CalendarContract.Attendees.ATTENDEE_TYPE + " INTEGER," +
439bafe9de156292f65b1079dd1eb586669f573d9e6Michael Chan                CalendarContract.Attendees.ATTENDEE_IDENTITY + " TEXT," +
440bafe9de156292f65b1079dd1eb586669f573d9e6Michael Chan                CalendarContract.Attendees.ATTENDEE_ID_NAMESPACE + " TEXT" +
4419f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                ");");
4429f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
4437cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio        db.execSQL("CREATE INDEX attendeesEventIdIndex ON " + Tables.ATTENDEES + " (" +
444b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Attendees.EVENT_ID +
4459f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                ");");
4469f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
4477cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio        db.execSQL("CREATE TABLE " + Tables.REMINDERS + " (" +
448b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Reminders._ID + " INTEGER PRIMARY KEY," +
449b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Reminders.EVENT_ID + " INTEGER," +
450b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Reminders.MINUTES + " INTEGER," +
451b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Reminders.METHOD + " INTEGER NOT NULL" +
452b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                " DEFAULT " + CalendarContract.Reminders.METHOD_DEFAULT +
4539f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                ");");
4549f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
4557cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio        db.execSQL("CREATE INDEX remindersEventIdIndex ON " + Tables.REMINDERS + " (" +
456b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Reminders.EVENT_ID +
4579f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                ");");
4589f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
4597e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff         // This table stores the Calendar notifications that have gone off.
4607cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio        db.execSQL("CREATE TABLE " + Tables.CALENDAR_ALERTS + " (" +
461b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.CalendarAlerts._ID + " INTEGER PRIMARY KEY," +
462b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.CalendarAlerts.EVENT_ID + " INTEGER," +
463b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.CalendarAlerts.BEGIN + " INTEGER NOT NULL," +      // UTC millis
464b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.CalendarAlerts.END + " INTEGER NOT NULL," +        // UTC millis
465b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.CalendarAlerts.ALARM_TIME + " INTEGER NOT NULL," + // UTC millis
466d5f4742d7ba16d791edd9fd33a1a2a42eeac709bRoboErik                // UTC millis
467b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.CalendarAlerts.CREATION_TIME + " INTEGER NOT NULL DEFAULT 0," +
468d5f4742d7ba16d791edd9fd33a1a2a42eeac709bRoboErik                // UTC millis
469b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.CalendarAlerts.RECEIVED_TIME + " INTEGER NOT NULL DEFAULT 0," +
470d5f4742d7ba16d791edd9fd33a1a2a42eeac709bRoboErik                // UTC millis
471b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.CalendarAlerts.NOTIFY_TIME + " INTEGER NOT NULL DEFAULT 0," +
472b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.CalendarAlerts.STATE + " INTEGER NOT NULL," +
473b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.CalendarAlerts.MINUTES + " INTEGER," +
4747cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                "UNIQUE (" +
475b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                    CalendarContract.CalendarAlerts.ALARM_TIME + ", " +
476b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                    CalendarContract.CalendarAlerts.BEGIN + ", " +
477b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                    CalendarContract.CalendarAlerts.EVENT_ID + ")" +
4789f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                ");");
4799f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
4807cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio        db.execSQL("CREATE INDEX calendarAlertsEventIdIndex ON " + Tables.CALENDAR_ALERTS + " (" +
481b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.CalendarAlerts.EVENT_ID +
4829f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                ");");
4839f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
4847cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio        db.execSQL("CREATE TABLE " + Tables.EXTENDED_PROPERTIES + " (" +
485b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.ExtendedProperties._ID + " INTEGER PRIMARY KEY," +
486b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.ExtendedProperties.EVENT_ID + " INTEGER," +
487b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.ExtendedProperties.NAME + " TEXT," +
488b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.ExtendedProperties.VALUE + " TEXT" +
4899f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                ");");
4909f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
4917cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio        db.execSQL("CREATE INDEX extendedPropertiesEventIdIndex ON " + Tables.EXTENDED_PROPERTIES
4927cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                + " (" +
493b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.ExtendedProperties.EVENT_ID +
4949f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                ");");
4959f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
4967cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio        createEventsView(db);
4977cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio
4989f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        // Trigger to remove data tied to an event when we delete that event.
4997cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio        db.execSQL("CREATE TRIGGER events_cleanup_delete DELETE ON " + Tables.EVENTS + " " +
5009f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                "BEGIN " +
5017cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                EVENTS_CLEANUP_TRIGGER_SQL +
5029f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                "END");
5039f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
5042f251c778c06d21ed7693a70f4a1268ff929242eRoboErik        // Triggers to update the color stored in an event or a calendar when
5052f251c778c06d21ed7693a70f4a1268ff929242eRoboErik        // the color_index is changed.
5062f251c778c06d21ed7693a70f4a1268ff929242eRoboErik        createColorsTriggers(db);
5072f251c778c06d21ed7693a70f4a1268ff929242eRoboErik
50834c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik        // Trigger to update exceptions when an original event updates its
50934c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik        // _sync_id
51034c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik        db.execSQL(CREATE_SYNC_ID_UPDATE_TRIGGER);
51134c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik
512470aa5bc291ca33d51dda356f38ac2954026da9aAlon Albert        scheduleSync(null /* all accounts */, false, null);
5139f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
5149f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
515c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik    private void createEventsTable(SQLiteDatabase db) {
516bcba82631ab0ee16efe58f0e0b0b9c18d93a6fd2Andy McFadden        // IMPORTANT: when adding new columns, be sure to update ALLOWED_IN_EXCEPTION and
517bcba82631ab0ee16efe58f0e0b0b9c18d93a6fd2Andy McFadden        // DONT_CLONE_INTO_EXCEPTION in CalendarProvider2.
518bcba82631ab0ee16efe58f0e0b0b9c18d93a6fd2Andy McFadden        //
519c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik        // TODO: do we need both dtend and duration?
52002f97c538fc46a08d857d2c807c76fd0eec12493RoboErik        // **When updating this be sure to also update LAST_SYNCED_EVENT_COLUMNS
521c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik        db.execSQL("CREATE TABLE " + Tables.EVENTS + " (" +
522935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden                CalendarContract.Events._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
523b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events._SYNC_ID + " TEXT," +
524b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.DIRTY + " INTEGER," +
5257a2531a4b68e9efe14353cc7f4a64a8c5613e5d3Alon Albert                CalendarContract.Events.MUTATORS + " TEXT," +
526b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.LAST_SYNCED + " INTEGER DEFAULT 0," +
527b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.CALENDAR_ID + " INTEGER NOT NULL," +
528b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.TITLE + " TEXT," +
529b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.EVENT_LOCATION + " TEXT," +
530b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.DESCRIPTION + " TEXT," +
531b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.EVENT_COLOR + " INTEGER," +
532387535fec9f646e0b7acb82d5354f2b5ebee4395RoboErik                CalendarContract.Events.EVENT_COLOR_KEY + " TEXT," +
533b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.STATUS + " INTEGER," +
534b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.SELF_ATTENDEE_STATUS + " INTEGER NOT NULL DEFAULT 0," +
535c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                // dtstart in millis since epoch
536b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.DTSTART + " INTEGER," +
537c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                // dtend in millis since epoch
538b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.DTEND + " INTEGER," +
539c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                // timezone for event
540b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.EVENT_TIMEZONE + " TEXT," +
541b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.DURATION + " TEXT," +
542b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.ALL_DAY + " INTEGER NOT NULL DEFAULT 0," +
543b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.ACCESS_LEVEL + " INTEGER NOT NULL DEFAULT 0," +
544b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.AVAILABILITY + " INTEGER NOT NULL DEFAULT 0," +
545b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.HAS_ALARM + " INTEGER NOT NULL DEFAULT 0," +
546b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.HAS_EXTENDED_PROPERTIES + " INTEGER NOT NULL DEFAULT 0," +
547b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.RRULE + " TEXT," +
548b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.RDATE + " TEXT," +
549b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.EXRULE + " TEXT," +
550b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.EXDATE + " TEXT," +
551b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.ORIGINAL_ID + " INTEGER," +
55234c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik                // ORIGINAL_SYNC_ID is the _sync_id of recurring event
553b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.ORIGINAL_SYNC_ID + " TEXT," +
55434c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik                // originalInstanceTime is in millis since epoch
555b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.ORIGINAL_INSTANCE_TIME + " INTEGER," +
556b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.ORIGINAL_ALL_DAY + " INTEGER," +
55734c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik                // lastDate is in millis since epoch
558b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.LAST_DATE + " INTEGER," +
559b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.HAS_ATTENDEE_DATA + " INTEGER NOT NULL DEFAULT 0," +
560b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.GUESTS_CAN_MODIFY + " INTEGER NOT NULL DEFAULT 0," +
561b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.GUESTS_CAN_INVITE_OTHERS + " INTEGER NOT NULL DEFAULT 1," +
562b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.GUESTS_CAN_SEE_GUESTS + " INTEGER NOT NULL DEFAULT 1," +
563b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.ORGANIZER + " STRING," +
564b2695bf3cfb173c4c5ba7bfd3c93ba8a51d65810Alon Albert                CalendarContract.Events.IS_ORGANIZER + " INTEGER," +
565b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.DELETED + " INTEGER NOT NULL DEFAULT 0," +
56634c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik                // timezone for event with allDay events are in local timezone
567b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.EVENT_END_TIMEZONE + " TEXT," +
568c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan                CalendarContract.Events.CUSTOM_APP_PACKAGE + " TEXT," +
569c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan                CalendarContract.Events.CUSTOM_APP_URI + " TEXT," +
570501e60bcb1b519d80723f7b64ba60bd079b8ec8dSara Ting                CalendarContract.Events.UID_2445 + " TEXT," +
57102f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                // SYNC_DATAX columns are available for use by sync adapters
572b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.SYNC_DATA1 + " TEXT," +
573b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.SYNC_DATA2 + " TEXT," +
574b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.SYNC_DATA3 + " TEXT," +
575b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.SYNC_DATA4 + " TEXT," +
576b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.SYNC_DATA5 + " TEXT," +
577b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.SYNC_DATA6 + " TEXT," +
578b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.SYNC_DATA7 + " TEXT," +
579b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.SYNC_DATA8 + " TEXT," +
580b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.SYNC_DATA9 + " TEXT," +
581b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.SYNC_DATA10 + " TEXT" + ");");
58202f97c538fc46a08d857d2c807c76fd0eec12493RoboErik
58302f97c538fc46a08d857d2c807c76fd0eec12493RoboErik        // **When updating this be sure to also update LAST_SYNCED_EVENT_COLUMNS
58434c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik
58534c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik        db.execSQL("CREATE INDEX eventsCalendarIdIndex ON " + Tables.EVENTS + " ("
586b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Events.CALENDAR_ID + ");");
58734c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik    }
58834c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik
5892f251c778c06d21ed7693a70f4a1268ff929242eRoboErik    private void createEventsTable307(SQLiteDatabase db) {
5902f251c778c06d21ed7693a70f4a1268ff929242eRoboErik        db.execSQL("CREATE TABLE Events ("
5912f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "_id INTEGER PRIMARY KEY AUTOINCREMENT,"
5922f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "_sync_id TEXT,"
5932f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "dirty INTEGER,"
5942f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "lastSynced INTEGER DEFAULT 0,"
5952f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "calendar_id INTEGER NOT NULL,"
5962f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "title TEXT,"
5972f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "eventLocation TEXT,"
5982f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "description TEXT,"
5992f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "eventColor INTEGER,"
6002f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "eventStatus INTEGER,"
6012f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "selfAttendeeStatus INTEGER NOT NULL DEFAULT 0,"
6022f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                // dtstart in millis since epoch
6032f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "dtstart INTEGER,"
6042f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                // dtend in millis since epoch
6052f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "dtend INTEGER,"
6062f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                // timezone for event
6072f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "eventTimezone TEXT,"
6082f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "duration TEXT,"
6092f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "allDay INTEGER NOT NULL DEFAULT 0,"
6102f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "accessLevel INTEGER NOT NULL DEFAULT 0,"
6112f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "availability INTEGER NOT NULL DEFAULT 0,"
6122f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "hasAlarm INTEGER NOT NULL DEFAULT 0,"
6132f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "hasExtendedProperties INTEGER NOT NULL DEFAULT 0,"
6142f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "rrule TEXT,"
6152f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "rdate TEXT,"
6162f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "exrule TEXT,"
6172f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "exdate TEXT,"
6182f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "original_id INTEGER,"
6192f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                // ORIGINAL_SYNC_ID is the _sync_id of recurring event
6202f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "original_sync_id TEXT,"
6212f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                // originalInstanceTime is in millis since epoch
6222f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "originalInstanceTime INTEGER,"
6232f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "originalAllDay INTEGER,"
6242f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                // lastDate is in millis since epoch
6252f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "lastDate INTEGER,"
6262f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "hasAttendeeData INTEGER NOT NULL DEFAULT 0,"
6272f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "guestsCanModify INTEGER NOT NULL DEFAULT 0,"
6282f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "guestsCanInviteOthers INTEGER NOT NULL DEFAULT 1,"
6292f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "guestsCanSeeGuests INTEGER NOT NULL DEFAULT 1,"
6302f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "organizer STRING,"
6312f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "deleted INTEGER NOT NULL DEFAULT 0,"
6322f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                // timezone for event with allDay events are in local timezone
6332f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "eventEndTimezone TEXT,"
6342f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                // SYNC_DATAX columns are available for use by sync adapters
6352f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "sync_data1 TEXT,"
6362f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "sync_data2 TEXT,"
6372f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "sync_data3 TEXT,"
6382f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "sync_data4 TEXT,"
6392f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "sync_data5 TEXT,"
6402f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "sync_data6 TEXT,"
6412f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "sync_data7 TEXT,"
6422f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "sync_data8 TEXT,"
6432f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "sync_data9 TEXT,"
6442f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "sync_data10 TEXT);");
6452f251c778c06d21ed7693a70f4a1268ff929242eRoboErik
6462f251c778c06d21ed7693a70f4a1268ff929242eRoboErik        // **When updating this be sure to also update LAST_SYNCED_EVENT_COLUMNS
6472f251c778c06d21ed7693a70f4a1268ff929242eRoboErik
6482f251c778c06d21ed7693a70f4a1268ff929242eRoboErik        db.execSQL("CREATE INDEX eventsCalendarIdIndex ON Events (calendar_id);");
6492f251c778c06d21ed7693a70f4a1268ff929242eRoboErik    }
6502f251c778c06d21ed7693a70f4a1268ff929242eRoboErik
65134c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik    // TODO Remove this method after merging all ICS upgrades
65234c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik    private void createEventsTable300(SQLiteDatabase db) {
65302f97c538fc46a08d857d2c807c76fd0eec12493RoboErik        db.execSQL("CREATE TABLE Events (" +
65402f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "_id INTEGER PRIMARY KEY," +
65502f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "_sync_id TEXT," +
65602f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "_sync_version TEXT," +
65734c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik                // sync time in UTC
65802f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "_sync_time TEXT,"  +
65902f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "_sync_local_id INTEGER," +
66002f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "dirty INTEGER," +
66134c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik                // sync mark to filter out new rows
66202f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "_sync_mark INTEGER," +
66302f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "calendar_id INTEGER NOT NULL," +
66402f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "htmlUri TEXT," +
66502f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "title TEXT," +
66602f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "eventLocation TEXT," +
66702f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "description TEXT," +
66802f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "eventStatus INTEGER," +
66902f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "selfAttendeeStatus INTEGER NOT NULL DEFAULT 0," +
67002f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "commentsUri TEXT," +
67134c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik                // dtstart in millis since epoch
67202f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "dtstart INTEGER," +
67334c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik                // dtend in millis since epoch
67402f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "dtend INTEGER," +
67534c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik                // timezone for event
67602f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "eventTimezone TEXT," +
67702f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "duration TEXT," +
67802f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "allDay INTEGER NOT NULL DEFAULT 0," +
67902f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "accessLevel INTEGER NOT NULL DEFAULT 0," +
68002f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "availability INTEGER NOT NULL DEFAULT 0," +
68102f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "hasAlarm INTEGER NOT NULL DEFAULT 0," +
68202f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "hasExtendedProperties INTEGER NOT NULL DEFAULT 0," +
68302f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "rrule TEXT," +
68402f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "rdate TEXT," +
68502f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "exrule TEXT," +
68602f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "exdate TEXT," +
687c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                // originalEvent is the _sync_id of recurring event
68802f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "original_sync_id TEXT," +
689c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                // originalInstanceTime is in millis since epoch
69002f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "originalInstanceTime INTEGER," +
69102f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "originalAllDay INTEGER," +
692c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                // lastDate is in millis since epoch
69302f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "lastDate INTEGER," +
69402f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "hasAttendeeData INTEGER NOT NULL DEFAULT 0," +
69502f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "guestsCanModify INTEGER NOT NULL DEFAULT 0," +
69602f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "guestsCanInviteOthers INTEGER NOT NULL DEFAULT 1," +
69702f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "guestsCanSeeGuests INTEGER NOT NULL DEFAULT 1," +
69802f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "organizer STRING," +
69902f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "deleted INTEGER NOT NULL DEFAULT 0," +
700c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                // timezone for event with allDay events are in local timezone
70102f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "eventEndTimezone TEXT," +
702c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                // syncAdapterData is available for use by sync adapters
70302f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "sync_data1 TEXT);");
704c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik
70502f97c538fc46a08d857d2c807c76fd0eec12493RoboErik        db.execSQL("CREATE INDEX eventsCalendarIdIndex ON Events (calendar_id);");
706c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik    }
707c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik
7089ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert    private void createCalendarsTable303(SQLiteDatabase db) {
7099ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert        db.execSQL("CREATE TABLE " + Tables.CALENDARS + " (" +
7109ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                "_id INTEGER PRIMARY KEY," +
7119ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                "account_name TEXT," +
7129ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                "account_type TEXT," +
7139ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                "_sync_id TEXT," +
7149ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                "_sync_version TEXT," +
7159ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                "_sync_time TEXT," +  // UTC
7169ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                "dirty INTEGER," +
7179ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                "name TEXT," +
7189ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                "displayName TEXT," +
7199ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                "calendar_color INTEGER," +
7209ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                "access_level INTEGER," +
7219ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                "visible INTEGER NOT NULL DEFAULT 1," +
7229ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                "sync_events INTEGER NOT NULL DEFAULT 0," +
7239ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                "calendar_location TEXT," +
7249ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                "calendar_timezone TEXT," +
7259ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                "ownerAccount TEXT, " +
7269ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                "canOrganizerRespond INTEGER NOT NULL DEFAULT 1," +
7279ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                "canModifyTimeZone INTEGER DEFAULT 1," +
7289ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                "maxReminders INTEGER DEFAULT 5," +
729bf986d8deeeed9566e0badeba89d4800533cbca6Andy McFadden                "allowedReminders TEXT DEFAULT '0,1'," +
7309ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                "deleted INTEGER NOT NULL DEFAULT 0," +
7319ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                "cal_sync1 TEXT," +
7329ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                "cal_sync2 TEXT," +
7339ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                "cal_sync3 TEXT," +
7349ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                "cal_sync4 TEXT," +
7359ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                "cal_sync5 TEXT," +
7369ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                "cal_sync6 TEXT" +
7379ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                ");");
7389ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert
7399ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert        // Trigger to remove a calendar's events when we delete the calendar
7409ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert        db.execSQL("CREATE TRIGGER calendar_cleanup DELETE ON " + Tables.CALENDARS + " " +
7419ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                "BEGIN " +
7429ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                CALENDAR_CLEANUP_TRIGGER_SQL +
7439ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                "END");
7449ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert    }
7459ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert
7462f251c778c06d21ed7693a70f4a1268ff929242eRoboErik    private void createColorsTable(SQLiteDatabase db) {
7472f251c778c06d21ed7693a70f4a1268ff929242eRoboErik
7482f251c778c06d21ed7693a70f4a1268ff929242eRoboErik        db.execSQL("CREATE TABLE " + Tables.COLORS + " (" +
7492f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                CalendarContract.Colors._ID + " INTEGER PRIMARY KEY," +
7502f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                CalendarContract.Colors.ACCOUNT_NAME + " TEXT NOT NULL," +
7512f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                CalendarContract.Colors.ACCOUNT_TYPE + " TEXT NOT NULL," +
7522f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                CalendarContract.Colors.DATA + " TEXT," +
7532f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                CalendarContract.Colors.COLOR_TYPE + " INTEGER NOT NULL," +
754387535fec9f646e0b7acb82d5354f2b5ebee4395RoboErik                CalendarContract.Colors.COLOR_KEY + " TEXT NOT NULL," +
7552f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                CalendarContract.Colors.COLOR + " INTEGER NOT NULL" +
7562f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                ");");
7572f251c778c06d21ed7693a70f4a1268ff929242eRoboErik    }
7582f251c778c06d21ed7693a70f4a1268ff929242eRoboErik
7592f251c778c06d21ed7693a70f4a1268ff929242eRoboErik    public void createColorsTriggers(SQLiteDatabase db) {
7602f251c778c06d21ed7693a70f4a1268ff929242eRoboErik        db.execSQL(CREATE_EVENT_COLOR_UPDATE_TRIGGER);
7612f251c778c06d21ed7693a70f4a1268ff929242eRoboErik        db.execSQL(CREATE_CALENDAR_COLOR_UPDATE_TRIGGER);
7622f251c778c06d21ed7693a70f4a1268ff929242eRoboErik    }
7632f251c778c06d21ed7693a70f4a1268ff929242eRoboErik
7641b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio    private void createCalendarsTable(SQLiteDatabase db) {
7651b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio        db.execSQL("CREATE TABLE " + Tables.CALENDARS + " (" +
766c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                Calendars._ID + " INTEGER PRIMARY KEY," +
767c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                Calendars.ACCOUNT_NAME + " TEXT," +
768c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                Calendars.ACCOUNT_TYPE + " TEXT," +
769c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                Calendars._SYNC_ID + " TEXT," +
770c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                Calendars.DIRTY + " INTEGER," +
7717a2531a4b68e9efe14353cc7f4a64a8c5613e5d3Alon Albert                Calendars.MUTATORS + " TEXT," +
772c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                Calendars.NAME + " TEXT," +
773c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                Calendars.CALENDAR_DISPLAY_NAME + " TEXT," +
774c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                Calendars.CALENDAR_COLOR + " INTEGER," +
775c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                Calendars.CALENDAR_COLOR_KEY + " TEXT," +
776c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                Calendars.CALENDAR_ACCESS_LEVEL + " INTEGER," +
777c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                Calendars.VISIBLE + " INTEGER NOT NULL DEFAULT 1," +
778c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                Calendars.SYNC_EVENTS + " INTEGER NOT NULL DEFAULT 0," +
779c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                Calendars.CALENDAR_LOCATION + " TEXT," +
780c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                Calendars.CALENDAR_TIME_ZONE + " TEXT," +
781c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                Calendars.OWNER_ACCOUNT + " TEXT, " +
782b2695bf3cfb173c4c5ba7bfd3c93ba8a51d65810Alon Albert                Calendars.IS_PRIMARY + " INTEGER, " +
783c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                Calendars.CAN_ORGANIZER_RESPOND + " INTEGER NOT NULL DEFAULT 1," +
784c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                Calendars.CAN_MODIFY_TIME_ZONE + " INTEGER DEFAULT 1," +
785c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                Calendars.CAN_PARTIALLY_UPDATE + " INTEGER DEFAULT 0," +
786c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                Calendars.MAX_REMINDERS + " INTEGER DEFAULT 5," +
787c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                Calendars.ALLOWED_REMINDERS + " TEXT DEFAULT '0,1'," +
788c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                Calendars.ALLOWED_AVAILABILITY + " TEXT DEFAULT '0,1'," +
789c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                Calendars.ALLOWED_ATTENDEE_TYPES + " TEXT DEFAULT '0,1,2'," +
790c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                Calendars.DELETED + " INTEGER NOT NULL DEFAULT 0," +
791c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                Calendars.CAL_SYNC1 + " TEXT," +
792c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                Calendars.CAL_SYNC2 + " TEXT," +
793c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                Calendars.CAL_SYNC3 + " TEXT," +
794c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                Calendars.CAL_SYNC4 + " TEXT," +
795c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                Calendars.CAL_SYNC5 + " TEXT," +
796c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                Calendars.CAL_SYNC6 + " TEXT," +
797c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                Calendars.CAL_SYNC7 + " TEXT," +
798c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                Calendars.CAL_SYNC8 + " TEXT," +
799c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                Calendars.CAL_SYNC9 + " TEXT," +
800c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                Calendars.CAL_SYNC10 + " TEXT" +
801fa332ecedc0c340109811552407142f6e4f600b2RoboErik                ");");
802fa332ecedc0c340109811552407142f6e4f600b2RoboErik
803fa332ecedc0c340109811552407142f6e4f600b2RoboErik        // Trigger to remove a calendar's events when we delete the calendar
804fa332ecedc0c340109811552407142f6e4f600b2RoboErik        db.execSQL("CREATE TRIGGER calendar_cleanup DELETE ON " + Tables.CALENDARS + " " +
805fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "BEGIN " +
806fa332ecedc0c340109811552407142f6e4f600b2RoboErik                CALENDAR_CLEANUP_TRIGGER_SQL +
807fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "END");
808fa332ecedc0c340109811552407142f6e4f600b2RoboErik    }
809fa332ecedc0c340109811552407142f6e4f600b2RoboErik
8102f251c778c06d21ed7693a70f4a1268ff929242eRoboErik    private void createCalendarsTable305(SQLiteDatabase db) {
8112f251c778c06d21ed7693a70f4a1268ff929242eRoboErik        db.execSQL("CREATE TABLE Calendars (" +
8122f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                "_id INTEGER PRIMARY KEY," +
8132f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                "account_name TEXT," +
8142f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                "account_type TEXT," +
8152f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                "_sync_id TEXT," +
8162f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                "dirty INTEGER," +
8172f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                "name TEXT," +
8182f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                "calendar_displayName TEXT," +
8192f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                "calendar_color INTEGER," +
8202f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                "calendar_access_level INTEGER," +
8212f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                "visible INTEGER NOT NULL DEFAULT 1," +
8222f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                "sync_events INTEGER NOT NULL DEFAULT 0," +
8232f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                "calendar_location TEXT," +
8242f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                "calendar_timezone TEXT," +
8252f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                "ownerAccount TEXT, " +
8262f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                "canOrganizerRespond INTEGER NOT NULL DEFAULT 1," +
8272f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                "canModifyTimeZone INTEGER DEFAULT 1," +
8282f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                "canPartiallyUpdate INTEGER DEFAULT 0," +
8292f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                "maxReminders INTEGER DEFAULT 5," +
8302f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                "allowedReminders TEXT DEFAULT '0,1'," +
8312f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                "deleted INTEGER NOT NULL DEFAULT 0," +
8322f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                "cal_sync1 TEXT," +
8332f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                "cal_sync2 TEXT," +
8342f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                "cal_sync3 TEXT," +
8352f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                "cal_sync4 TEXT," +
8362f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                "cal_sync5 TEXT," +
8372f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                "cal_sync6 TEXT," +
8382f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                "cal_sync7 TEXT," +
8392f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                "cal_sync8 TEXT," +
8402f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                "cal_sync9 TEXT," +
8412f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                "cal_sync10 TEXT" +
8422f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                ");");
8432f251c778c06d21ed7693a70f4a1268ff929242eRoboErik
8442f251c778c06d21ed7693a70f4a1268ff929242eRoboErik        // Trigger to remove a calendar's events when we delete the calendar
8452f251c778c06d21ed7693a70f4a1268ff929242eRoboErik        db.execSQL("CREATE TRIGGER calendar_cleanup DELETE ON Calendars " +
8462f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                "BEGIN " +
8472f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                "DELETE FROM Events WHERE calendar_id=old._id;" +
8482f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                "END");
8492f251c778c06d21ed7693a70f4a1268ff929242eRoboErik    }
8502f251c778c06d21ed7693a70f4a1268ff929242eRoboErik
851fa332ecedc0c340109811552407142f6e4f600b2RoboErik    private void createCalendarsTable300(SQLiteDatabase db) {
852fa332ecedc0c340109811552407142f6e4f600b2RoboErik        db.execSQL("CREATE TABLE " + Tables.CALENDARS + " (" +
853fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "_id INTEGER PRIMARY KEY," +
854fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "account_name TEXT," +
855fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "account_type TEXT," +
856fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "_sync_id TEXT," +
857fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "_sync_version TEXT," +
858fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "_sync_time TEXT," +  // UTC
859fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "dirty INTEGER," +
860fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "name TEXT," +
861fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "displayName TEXT," +
862fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "calendar_color INTEGER," +
863fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "access_level INTEGER," +
864fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "visible INTEGER NOT NULL DEFAULT 1," +
865fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "sync_events INTEGER NOT NULL DEFAULT 0," +
866fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "calendar_location TEXT," +
867fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "calendar_timezone TEXT," +
868fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "ownerAccount TEXT, " +
869fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "canOrganizerRespond INTEGER NOT NULL DEFAULT 1," +
870fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "canModifyTimeZone INTEGER DEFAULT 1," +
871fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "maxReminders INTEGER DEFAULT 5," +
872fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "allowedReminders TEXT DEFAULT '0,1,2'," +
873fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "deleted INTEGER NOT NULL DEFAULT 0," +
874fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "sync1 TEXT," +
875fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "sync2 TEXT," +
876fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "sync3 TEXT," +
877fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "sync4 TEXT," +
878fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "sync5 TEXT," +
879fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "sync6 TEXT" +
8801b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio                ");");
8811b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio
8821b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio        // Trigger to remove a calendar's events when we delete the calendar
8831b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio        db.execSQL("CREATE TRIGGER calendar_cleanup DELETE ON " + Tables.CALENDARS + " " +
8841b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio                "BEGIN " +
8851b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio                CALENDAR_CLEANUP_TRIGGER_SQL +
8861b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio                "END");
8871b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio    }
8881b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio
889c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik    private void createCalendarsTable205(SQLiteDatabase db) {
890c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik        db.execSQL("CREATE TABLE Calendars (" +
891c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "_id INTEGER PRIMARY KEY," +
892c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "_sync_account TEXT," +
893c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "_sync_account_type TEXT," +
894c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "_sync_id TEXT," +
895c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "_sync_version TEXT," +
896c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "_sync_time TEXT," +  // UTC
897c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "_sync_dirty INTEGER," +
898c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "name TEXT," +
899c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "displayName TEXT," +
900c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "color INTEGER," +
901c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "access_level INTEGER," +
902c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "visible INTEGER NOT NULL DEFAULT 1," +
903c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "sync_events INTEGER NOT NULL DEFAULT 0," +
904c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "location TEXT," +
905c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "timezone TEXT," +
906c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "ownerAccount TEXT, " +
907c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "canOrganizerRespond INTEGER NOT NULL DEFAULT 1," +
908c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "canModifyTimeZone INTEGER DEFAULT 1, " +
909c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "maxReminders INTEGER DEFAULT 5," +
910c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "deleted INTEGER NOT NULL DEFAULT 0," +
911c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "sync1 TEXT," +
912c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "sync2 TEXT," +
913c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "sync3 TEXT," +
914c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "sync4 TEXT," +
915c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "sync5 TEXT," +
916c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "sync6 TEXT" +
917c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                ");");
918c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik
919c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik        createCalendarsCleanup200(db);
920c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik    }
921c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik
922180076a810558478f55ade53ebef0a2ddfa6bbc0Andy McFadden    private void createCalendarsTable202(SQLiteDatabase db) {
9232cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("CREATE TABLE Calendars (" +
9242cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_id INTEGER PRIMARY KEY," +
9252cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_account TEXT," +
9262cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_account_type TEXT," +
9272cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_id TEXT," +
9282cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_version TEXT," +
9292cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_time TEXT," +  // UTC
9302cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_local_id INTEGER," +
9312cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_dirty INTEGER," +
9322cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_mark INTEGER," + // Used to filter out new rows
9332cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "name TEXT," +
9342cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "displayName TEXT," +
9352cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "color INTEGER," +
9362cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "access_level INTEGER," +
9372cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "selected INTEGER NOT NULL DEFAULT 1," +
9382cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "sync_events INTEGER NOT NULL DEFAULT 0," +
9392cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "location TEXT," +
9402cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "timezone TEXT," +
9412cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "ownerAccount TEXT, " +
9422cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "organizerCanRespond INTEGER NOT NULL DEFAULT 1," +
9432cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "deleted INTEGER NOT NULL DEFAULT 0," +
9442cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "sync1 TEXT," +
9452cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "sync2 TEXT," +
9462cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "sync3 TEXT," +
9472cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "sync4 TEXT," +
9482cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "sync5 TEXT" +
9492cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                ");");
9502cff10f1a005bd7302245d4c680cf851193c3a97RoboErik
9514067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden        createCalendarsCleanup200(db);
9522cff10f1a005bd7302245d4c680cf851193c3a97RoboErik    }
9532cff10f1a005bd7302245d4c680cf851193c3a97RoboErik
9542cff10f1a005bd7302245d4c680cf851193c3a97RoboErik    private void createCalendarsTable200(SQLiteDatabase db) {
9552cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("CREATE TABLE Calendars (" +
9562cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_id INTEGER PRIMARY KEY," +
9572cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_account TEXT," +
9582cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_account_type TEXT," +
9592cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_id TEXT," +
9602cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_version TEXT," +
9612cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_time TEXT," +  // UTC
9622cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_local_id INTEGER," +
9632cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_dirty INTEGER," +
9642cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_mark INTEGER," + // Used to filter out new rows
9652cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "name TEXT," +
9662cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "displayName TEXT," +
9672cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "hidden INTEGER NOT NULL DEFAULT 0," +
9682cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "color INTEGER," +
9692cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "access_level INTEGER," +
9702cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "selected INTEGER NOT NULL DEFAULT 1," +
9712cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "sync_events INTEGER NOT NULL DEFAULT 0," +
9722cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "location TEXT," +
9732cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "timezone TEXT," +
9742cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "ownerAccount TEXT, " +
9752cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "organizerCanRespond INTEGER NOT NULL DEFAULT 1," +
9762cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "deleted INTEGER NOT NULL DEFAULT 0," +
9772cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "sync1 TEXT," +
9782cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "sync2 TEXT," +
9792cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "sync3 TEXT" +
9802cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                ");");
9812cff10f1a005bd7302245d4c680cf851193c3a97RoboErik
9824067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden        createCalendarsCleanup200(db);
9834067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden    }
9844067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden
9854067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden    /** Trigger to remove a calendar's events when we delete the calendar */
9864067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden    private void createCalendarsCleanup200(SQLiteDatabase db) {
9872cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("CREATE TRIGGER calendar_cleanup DELETE ON Calendars " +
9882cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "BEGIN " +
9892cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "DELETE FROM Events WHERE calendar_id=old._id;" +
9902cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "END");
9912cff10f1a005bd7302245d4c680cf851193c3a97RoboErik    }
9922cff10f1a005bd7302245d4c680cf851193c3a97RoboErik
9931599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio    private void createCalendarMetaDataTable(SQLiteDatabase db) {
9947cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio        db.execSQL("CREATE TABLE " + Tables.CALENDAR_META_DATA + " (" +
995b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.CalendarMetaData._ID + " INTEGER PRIMARY KEY," +
996b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.CalendarMetaData.LOCAL_TIMEZONE + " TEXT," +
997b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.CalendarMetaData.MIN_INSTANCE + " INTEGER," +      // UTC millis
998b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.CalendarMetaData.MAX_INSTANCE + " INTEGER" +       // UTC millis
9991599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio                ");");
10001599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio    }
10011599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio
10022cff10f1a005bd7302245d4c680cf851193c3a97RoboErik    private void createCalendarMetaDataTable59(SQLiteDatabase db) {
10032cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("CREATE TABLE CalendarMetaData (" +
10042cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_id INTEGER PRIMARY KEY," +
10052cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "localTimezone TEXT," +
10062cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "minInstance INTEGER," +      // UTC millis
10072cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "maxInstance INTEGER" +       // UTC millis
10082cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                ");");
10092cff10f1a005bd7302245d4c680cf851193c3a97RoboErik    }
10102cff10f1a005bd7302245d4c680cf851193c3a97RoboErik
1011315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio    private void createCalendarCacheTable(SQLiteDatabase db, String oldTimezoneDbVersion) {
1012754b6d0e96c7df4cb649a48cde21b72c3dcedf4aErik        // This is a hack because versioning skipped version number 61 of schema
1013754b6d0e96c7df4cb649a48cde21b72c3dcedf4aErik        // TODO after version 70 this can be removed
10147cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio        db.execSQL("DROP TABLE IF EXISTS " + Tables.CALENDAR_CACHE + ";");
1015754b6d0e96c7df4cb649a48cde21b72c3dcedf4aErik
1016754b6d0e96c7df4cb649a48cde21b72c3dcedf4aErik        // IF NOT EXISTS should be normal pattern for table creation
10177cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio        db.execSQL("CREATE TABLE IF NOT EXISTS " + Tables.CALENDAR_CACHE + " (" +
10187cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                CalendarCache.COLUMN_NAME_ID + " INTEGER PRIMARY KEY," +
10197cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                CalendarCache.COLUMN_NAME_KEY + " TEXT NOT NULL," +
10207cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                CalendarCache.COLUMN_NAME_VALUE + " TEXT" +
1021ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio                ");");
1022ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio
1023315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        initCalendarCacheTable(db, oldTimezoneDbVersion);
10242cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        updateCalendarCacheTable(db);
1025b492524403ca34b0cb03bfad6456909494479925Fabrice Di Meglio    }
1026b492524403ca34b0cb03bfad6456909494479925Fabrice Di Meglio
1027315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio    private void initCalendarCacheTable(SQLiteDatabase db, String oldTimezoneDbVersion) {
1028315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        String timezoneDbVersion = (oldTimezoneDbVersion != null) ?
1029315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio                oldTimezoneDbVersion : CalendarCache.DEFAULT_TIMEZONE_DATABASE_VERSION;
1030315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio
1031315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        // Set the default timezone database version
1032258fc0a0054d6aba8556921c270379cea6bf3de1Fabrice Di Meglio        db.execSQL("INSERT OR REPLACE INTO " + Tables.CALENDAR_CACHE +
1033258fc0a0054d6aba8556921c270379cea6bf3de1Fabrice Di Meglio                " (" + CalendarCache.COLUMN_NAME_ID + ", " +
1034258fc0a0054d6aba8556921c270379cea6bf3de1Fabrice Di Meglio                CalendarCache.COLUMN_NAME_KEY + ", " +
1035258fc0a0054d6aba8556921c270379cea6bf3de1Fabrice Di Meglio                CalendarCache.COLUMN_NAME_VALUE + ") VALUES (" +
1036b492524403ca34b0cb03bfad6456909494479925Fabrice Di Meglio                CalendarCache.KEY_TIMEZONE_DATABASE_VERSION.hashCode() + "," +
1037470aa5bc291ca33d51dda356f38ac2954026da9aAlon Albert                "'" + CalendarCache.KEY_TIMEZONE_DATABASE_VERSION + "'," +
1038315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio                "'" + timezoneDbVersion + "'" +
1039315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio                ");");
1040315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio    }
1041315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio
10422cff10f1a005bd7302245d4c680cf851193c3a97RoboErik    private void updateCalendarCacheTable(SQLiteDatabase db) {
1043315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        // Define the default timezone type for Instances timezone management
1044258fc0a0054d6aba8556921c270379cea6bf3de1Fabrice Di Meglio        db.execSQL("INSERT INTO " + Tables.CALENDAR_CACHE +
1045258fc0a0054d6aba8556921c270379cea6bf3de1Fabrice Di Meglio                " (" + CalendarCache.COLUMN_NAME_ID + ", " +
1046258fc0a0054d6aba8556921c270379cea6bf3de1Fabrice Di Meglio                CalendarCache.COLUMN_NAME_KEY + ", " +
1047258fc0a0054d6aba8556921c270379cea6bf3de1Fabrice Di Meglio                CalendarCache.COLUMN_NAME_VALUE + ") VALUES (" +
1048315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio                CalendarCache.KEY_TIMEZONE_TYPE.hashCode() + "," +
1049315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio                "'" + CalendarCache.KEY_TIMEZONE_TYPE + "',"  +
1050315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio                "'" + CalendarCache.TIMEZONE_TYPE_AUTO + "'" +
1051315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio                ");");
1052315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio
1053315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        String defaultTimezone = TimeZone.getDefault().getID();
1054315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio
1055315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        // Define the default timezone for Instances
1056258fc0a0054d6aba8556921c270379cea6bf3de1Fabrice Di Meglio        db.execSQL("INSERT INTO " + Tables.CALENDAR_CACHE +
1057258fc0a0054d6aba8556921c270379cea6bf3de1Fabrice Di Meglio                " (" + CalendarCache.COLUMN_NAME_ID + ", " +
1058258fc0a0054d6aba8556921c270379cea6bf3de1Fabrice Di Meglio                CalendarCache.COLUMN_NAME_KEY + ", " +
1059258fc0a0054d6aba8556921c270379cea6bf3de1Fabrice Di Meglio                CalendarCache.COLUMN_NAME_VALUE + ") VALUES (" +
1060315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio                CalendarCache.KEY_TIMEZONE_INSTANCES.hashCode() + "," +
1061315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio                "'" + CalendarCache.KEY_TIMEZONE_INSTANCES + "',"  +
1062315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio                "'" + defaultTimezone + "'" +
1063315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio                ");");
1064315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio
1065315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        // Define the default previous timezone for Instances
1066258fc0a0054d6aba8556921c270379cea6bf3de1Fabrice Di Meglio        db.execSQL("INSERT INTO " + Tables.CALENDAR_CACHE +
1067258fc0a0054d6aba8556921c270379cea6bf3de1Fabrice Di Meglio                " (" + CalendarCache.COLUMN_NAME_ID + ", " +
1068258fc0a0054d6aba8556921c270379cea6bf3de1Fabrice Di Meglio                CalendarCache.COLUMN_NAME_KEY + ", " +
1069258fc0a0054d6aba8556921c270379cea6bf3de1Fabrice Di Meglio                CalendarCache.COLUMN_NAME_VALUE + ") VALUES (" +
1070315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio                CalendarCache.KEY_TIMEZONE_INSTANCES_PREVIOUS.hashCode() + "," +
1071315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio                "'" + CalendarCache.KEY_TIMEZONE_INSTANCES_PREVIOUS + "',"  +
1072315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio                "'" + defaultTimezone + "'" +
1073ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio                ");");
1074ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio    }
1075ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio
10762cff10f1a005bd7302245d4c680cf851193c3a97RoboErik    private void initCalendarCacheTable203(SQLiteDatabase db, String oldTimezoneDbVersion) {
10772cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        String timezoneDbVersion = (oldTimezoneDbVersion != null) ?
10782cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                oldTimezoneDbVersion : "2009s";
10792cff10f1a005bd7302245d4c680cf851193c3a97RoboErik
10802cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        // Set the default timezone database version
10812cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("INSERT OR REPLACE INTO CalendarCache" +
10822cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                " (_id, " +
10832cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "key, " +
10842cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "value) VALUES (" +
10852cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "timezoneDatabaseVersion".hashCode() + "," +
10862cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "'timezoneDatabaseVersion',"  +
10872cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "'" + timezoneDbVersion + "'" +
10882cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                ");");
10892cff10f1a005bd7302245d4c680cf851193c3a97RoboErik    }
10902cff10f1a005bd7302245d4c680cf851193c3a97RoboErik
10912cff10f1a005bd7302245d4c680cf851193c3a97RoboErik    private void updateCalendarCacheTableTo203(SQLiteDatabase db) {
10922cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        // Define the default timezone type for Instances timezone management
10932cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("INSERT INTO CalendarCache" +
10942cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                " (_id, key, value) VALUES (" +
10952cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "timezoneType".hashCode() + "," +
10962cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "'timezoneType',"  +
10972cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "'auto'" +
10982cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                ");");
10992cff10f1a005bd7302245d4c680cf851193c3a97RoboErik
11002cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        String defaultTimezone = TimeZone.getDefault().getID();
11012cff10f1a005bd7302245d4c680cf851193c3a97RoboErik
11022cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        // Define the default timezone for Instances
11032cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("INSERT INTO CalendarCache" +
11042cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                " (_id, key, value) VALUES (" +
11052cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "timezoneInstances".hashCode() + "," +
11062cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "'timezoneInstances',"  +
11072cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "'" + defaultTimezone + "'" +
11082cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                ");");
11092cff10f1a005bd7302245d4c680cf851193c3a97RoboErik
11102cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        // Define the default previous timezone for Instances
11112cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("INSERT INTO CalendarCache" +
11122cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                " (_id, key, value) VALUES (" +
11132cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "timezoneInstancesPrevious".hashCode() + "," +
11142cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "'timezoneInstancesPrevious',"  +
11152cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "'" + defaultTimezone + "'" +
11162cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                ");");
11172cff10f1a005bd7302245d4c680cf851193c3a97RoboErik    }
11182cff10f1a005bd7302245d4c680cf851193c3a97RoboErik
1119935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden    /**
1120935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden     * Removes orphaned data from the database.  Specifically:
1121935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden     * <ul>
1122935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden     * <li>Attendees with an event_id for a nonexistent Event
1123935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden     * <li>Reminders with an event_id for a nonexistent Event
1124935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden     * </ul>
1125935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden     */
1126935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden    static void removeOrphans(SQLiteDatabase db) {
1127935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden        if (false) {        // debug mode
1128935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            String SELECT_ATTENDEES_ORPHANS = "SELECT " +
1129935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden                    Attendees._ID + ", " + Attendees.EVENT_ID + " FROM " + Tables.ATTENDEES +
1130935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden                    " WHERE " + WHERE_ATTENDEES_ORPHANS;
1131935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden
1132935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            Cursor cursor = null;
1133935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            try {
1134935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden                Log.i(TAG, "Attendees orphans:");
1135935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden                cursor = db.rawQuery(SELECT_ATTENDEES_ORPHANS, null);
1136935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden                DatabaseUtils.dumpCursor(cursor);
1137935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            } finally {
1138935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden                if (cursor != null) {
1139935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden                    cursor.close();
1140935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden                }
1141935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            }
1142935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden
1143935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            String SELECT_REMINDERS_ORPHANS = "SELECT " +
1144935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden                    Attendees._ID + ", " + Reminders.EVENT_ID + " FROM " + Tables.REMINDERS +
1145935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden                    " WHERE " + WHERE_REMINDERS_ORPHANS;
1146935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            cursor = null;
1147935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            try {
1148935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden                Log.i(TAG, "Reminders orphans:");
1149935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden                cursor = db.rawQuery(SELECT_REMINDERS_ORPHANS, null);
1150935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden                DatabaseUtils.dumpCursor(cursor);
1151935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            } finally {
1152935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden                if (cursor != null) {
1153935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden                    cursor.close();
1154935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden                }
1155935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            }
1156935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden
1157935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            return;
1158935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden        }
1159935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden
1160935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden        Log.d(TAG, "Checking for orphaned entries");
1161935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden        int count;
1162935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden
1163935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden        count = db.delete(Tables.ATTENDEES, WHERE_ATTENDEES_ORPHANS, null);
1164935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden        if (count != 0) {
1165935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            Log.i(TAG, "Deleted " + count + " orphaned Attendees");
1166935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden        }
1167935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden
1168935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden        count = db.delete(Tables.REMINDERS, WHERE_REMINDERS_ORPHANS, null);
1169935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden        if (count != 0) {
1170935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            Log.i(TAG, "Deleted " + count + " orphaned Reminders");
1171935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden        }
1172935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden    }
1173935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden
1174935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden
11759f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    @Override
11769f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
11777544af675ce2fd78f33198e5e9194f2bc7bd129fAndy McFadden        Log.i(TAG, "Upgrading DB from version " + oldVersion + " to " + newVersion);
11787544af675ce2fd78f33198e5e9194f2bc7bd129fAndy McFadden        long startWhen = System.nanoTime();
11797544af675ce2fd78f33198e5e9194f2bc7bd129fAndy McFadden
1180ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        if (oldVersion < 49) {
11819f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            dropTables(db);
11820d8699eedb0f3bcec1854b9753ae59154a122726Michael Chan            bootstrapDB(db);
11830d8699eedb0f3bcec1854b9753ae59154a122726Michael Chan            return;
11849f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
11859f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
11861599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio        // From schema versions 59 to version 66, the CalendarMetaData table definition had lost
11871599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio        // the primary key leading to having the CalendarMetaData with multiple rows instead of
11881599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio        // only one. The Instance table was then corrupted (during Instance expansion we are using
11891599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio        // the localTimezone, minInstance and maxInstance from CalendarMetaData table.
11901599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio        // This boolean helps us tracking the need to recreate the CalendarMetaData table and
11911599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio        // clear the Instance table (and thus force an Instance expansion).
1192679d544f38aa33d00c12884b987d8f8af2a6a6d3Fabrice Di Meglio        boolean recreateMetaDataAndInstances = (oldVersion >= 59 && oldVersion <= 66);
11932cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        boolean createEventsView = false;
11941599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio
1195a6357118c223d00ed722ecd40ecdda92d705d211Erik        try {
1196a6357118c223d00ed722ecd40ecdda92d705d211Erik            if (oldVersion < 51) {
1197a6357118c223d00ed722ecd40ecdda92d705d211Erik                upgradeToVersion51(db); // From 50 or 51
1198a6357118c223d00ed722ecd40ecdda92d705d211Erik                oldVersion = 51;
1199a6357118c223d00ed722ecd40ecdda92d705d211Erik            }
1200a6357118c223d00ed722ecd40ecdda92d705d211Erik            if (oldVersion == 51) {
1201a6357118c223d00ed722ecd40ecdda92d705d211Erik                upgradeToVersion52(db);
1202a6357118c223d00ed722ecd40ecdda92d705d211Erik                oldVersion += 1;
1203a6357118c223d00ed722ecd40ecdda92d705d211Erik            }
1204a6357118c223d00ed722ecd40ecdda92d705d211Erik            if (oldVersion == 52) {
1205a6357118c223d00ed722ecd40ecdda92d705d211Erik                upgradeToVersion53(db);
1206a6357118c223d00ed722ecd40ecdda92d705d211Erik                oldVersion += 1;
1207a6357118c223d00ed722ecd40ecdda92d705d211Erik            }
1208a6357118c223d00ed722ecd40ecdda92d705d211Erik            if (oldVersion == 53) {
1209a6357118c223d00ed722ecd40ecdda92d705d211Erik                upgradeToVersion54(db);
1210a6357118c223d00ed722ecd40ecdda92d705d211Erik                oldVersion += 1;
1211a6357118c223d00ed722ecd40ecdda92d705d211Erik            }
1212a6357118c223d00ed722ecd40ecdda92d705d211Erik            if (oldVersion == 54) {
1213a6357118c223d00ed722ecd40ecdda92d705d211Erik                upgradeToVersion55(db);
1214a6357118c223d00ed722ecd40ecdda92d705d211Erik                oldVersion += 1;
1215a6357118c223d00ed722ecd40ecdda92d705d211Erik            }
1216a6357118c223d00ed722ecd40ecdda92d705d211Erik            if (oldVersion == 55 || oldVersion == 56) {
1217a6357118c223d00ed722ecd40ecdda92d705d211Erik                // Both require resync, so just schedule it once
1218a6357118c223d00ed722ecd40ecdda92d705d211Erik                upgradeResync(db);
1219a6357118c223d00ed722ecd40ecdda92d705d211Erik            }
1220a6357118c223d00ed722ecd40ecdda92d705d211Erik            if (oldVersion == 55) {
1221a6357118c223d00ed722ecd40ecdda92d705d211Erik                upgradeToVersion56(db);
1222a6357118c223d00ed722ecd40ecdda92d705d211Erik                oldVersion += 1;
1223a6357118c223d00ed722ecd40ecdda92d705d211Erik            }
1224a6357118c223d00ed722ecd40ecdda92d705d211Erik            if (oldVersion == 56) {
1225a6357118c223d00ed722ecd40ecdda92d705d211Erik                upgradeToVersion57(db);
1226a6357118c223d00ed722ecd40ecdda92d705d211Erik                oldVersion += 1;
1227a6357118c223d00ed722ecd40ecdda92d705d211Erik            }
1228a6357118c223d00ed722ecd40ecdda92d705d211Erik            if (oldVersion == 57) {
1229a6357118c223d00ed722ecd40ecdda92d705d211Erik                // Changes are undone upgrading to 60, so don't do anything.
1230a6357118c223d00ed722ecd40ecdda92d705d211Erik                oldVersion += 1;
1231a6357118c223d00ed722ecd40ecdda92d705d211Erik            }
1232a6357118c223d00ed722ecd40ecdda92d705d211Erik            if (oldVersion == 58) {
1233a6357118c223d00ed722ecd40ecdda92d705d211Erik                upgradeToVersion59(db);
1234a6357118c223d00ed722ecd40ecdda92d705d211Erik                oldVersion += 1;
1235a6357118c223d00ed722ecd40ecdda92d705d211Erik            }
1236a6357118c223d00ed722ecd40ecdda92d705d211Erik            if (oldVersion == 59) {
1237a6357118c223d00ed722ecd40ecdda92d705d211Erik                upgradeToVersion60(db);
12382cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                createEventsView = true;
1239a6357118c223d00ed722ecd40ecdda92d705d211Erik                oldVersion += 1;
1240a6357118c223d00ed722ecd40ecdda92d705d211Erik            }
1241a6357118c223d00ed722ecd40ecdda92d705d211Erik            if (oldVersion == 60) {
1242a6357118c223d00ed722ecd40ecdda92d705d211Erik                upgradeToVersion61(db);
1243a6357118c223d00ed722ecd40ecdda92d705d211Erik                oldVersion += 1;
1244a6357118c223d00ed722ecd40ecdda92d705d211Erik            }
1245a6357118c223d00ed722ecd40ecdda92d705d211Erik            if (oldVersion == 61) {
1246a6357118c223d00ed722ecd40ecdda92d705d211Erik                upgradeToVersion62(db);
1247a6357118c223d00ed722ecd40ecdda92d705d211Erik                oldVersion += 1;
1248a6357118c223d00ed722ecd40ecdda92d705d211Erik            }
1249a6357118c223d00ed722ecd40ecdda92d705d211Erik            if (oldVersion == 62) {
12502cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                createEventsView = true;
1251a6357118c223d00ed722ecd40ecdda92d705d211Erik                oldVersion += 1;
1252a6357118c223d00ed722ecd40ecdda92d705d211Erik            }
1253a6357118c223d00ed722ecd40ecdda92d705d211Erik            if (oldVersion == 63) {
1254a6357118c223d00ed722ecd40ecdda92d705d211Erik                upgradeToVersion64(db);
1255a6357118c223d00ed722ecd40ecdda92d705d211Erik                oldVersion += 1;
1256a6357118c223d00ed722ecd40ecdda92d705d211Erik            }
1257a6357118c223d00ed722ecd40ecdda92d705d211Erik            if (oldVersion == 64) {
12582cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                createEventsView = true;
1259a6357118c223d00ed722ecd40ecdda92d705d211Erik                oldVersion += 1;
1260a6357118c223d00ed722ecd40ecdda92d705d211Erik            }
1261a6357118c223d00ed722ecd40ecdda92d705d211Erik            if (oldVersion == 65) {
1262a6357118c223d00ed722ecd40ecdda92d705d211Erik                upgradeToVersion66(db);
1263a6357118c223d00ed722ecd40ecdda92d705d211Erik                oldVersion += 1;
1264a6357118c223d00ed722ecd40ecdda92d705d211Erik            }
12651599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio            if (oldVersion == 66) {
1266679d544f38aa33d00c12884b987d8f8af2a6a6d3Fabrice Di Meglio                // Changes are done thru recreateMetaDataAndInstances() method
12671599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio                oldVersion += 1;
12681599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio            }
1269679d544f38aa33d00c12884b987d8f8af2a6a6d3Fabrice Di Meglio            if (recreateMetaDataAndInstances) {
12702cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                recreateMetaDataAndInstances67(db);
1271679d544f38aa33d00c12884b987d8f8af2a6a6d3Fabrice Di Meglio            }
127243b3eba05ef67bdd4b0a2b285b6ed2b377c136c5Fabrice Di Meglio            if (oldVersion == 67 || oldVersion == 68) {
1273e3730b9dce00439666e7ef324a28263a0ee92032Erik                upgradeToVersion69(db);
1274e3730b9dce00439666e7ef324a28263a0ee92032Erik                oldVersion = 69;
12757b40dde3168f4af2c757cb43955aa3bfe1668666Erik            }
1276b492524403ca34b0cb03bfad6456909494479925Fabrice Di Meglio            // 69. 70 are for Froyo/old Gingerbread only and 100s are for Gingerbread only
1277b492524403ca34b0cb03bfad6456909494479925Fabrice Di Meglio            // 70 and 71 have been for Honeycomb but no more used
1278b492524403ca34b0cb03bfad6456909494479925Fabrice Di Meglio            // 72 and 73 and 74 were for Honeycomb only but are considered as obsolete for enabling
1279b492524403ca34b0cb03bfad6456909494479925Fabrice Di Meglio            // room for Froyo version numbers
1280b492524403ca34b0cb03bfad6456909494479925Fabrice Di Meglio            if(oldVersion == 69) {
1281315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio                upgradeToVersion200(db);
12822cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                createEventsView = true;
1283315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio                oldVersion = 200;
128443b3eba05ef67bdd4b0a2b285b6ed2b377c136c5Fabrice Di Meglio            }
1285b492524403ca34b0cb03bfad6456909494479925Fabrice Di Meglio            if (oldVersion == 70) {
1286b492524403ca34b0cb03bfad6456909494479925Fabrice Di Meglio                upgradeToVersion200(db);
1287b492524403ca34b0cb03bfad6456909494479925Fabrice Di Meglio                oldVersion = 200;
1288b492524403ca34b0cb03bfad6456909494479925Fabrice Di Meglio            }
1289b492524403ca34b0cb03bfad6456909494479925Fabrice Di Meglio            if (oldVersion == 100) {
12907544af675ce2fd78f33198e5e9194f2bc7bd129fAndy McFadden                // note we skip past v101 and v102
1291b492524403ca34b0cb03bfad6456909494479925Fabrice Di Meglio                upgradeToVersion200(db);
1292b492524403ca34b0cb03bfad6456909494479925Fabrice Di Meglio                oldVersion = 200;
1293c59a6b5d8ff6b941fc44e9181e668fe0ec7df088Fabrice Di Meglio            }
1294315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio            boolean need203Update = true;
12957544af675ce2fd78f33198e5e9194f2bc7bd129fAndy McFadden            if (oldVersion == 101 || oldVersion == 102) {
12967544af675ce2fd78f33198e5e9194f2bc7bd129fAndy McFadden                // v101 is v100 plus updateCalendarCacheTableTo203().
12977544af675ce2fd78f33198e5e9194f2bc7bd129fAndy McFadden                // v102 is v101 with Event._id changed to autoincrement.
12987544af675ce2fd78f33198e5e9194f2bc7bd129fAndy McFadden                // Upgrade to 200 and skip the 203 update.
12997544af675ce2fd78f33198e5e9194f2bc7bd129fAndy McFadden                upgradeToVersion200(db);
1300315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio                oldVersion = 200;
1301315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio                need203Update = false;
1302315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio            }
1303b492524403ca34b0cb03bfad6456909494479925Fabrice Di Meglio            if (oldVersion == 200) {
1304b492524403ca34b0cb03bfad6456909494479925Fabrice Di Meglio                upgradeToVersion201(db);
13057e7329964ddd60c98e93a7eda18b68944a630382Fabrice Di Meglio                oldVersion += 1;
13067e7329964ddd60c98e93a7eda18b68944a630382Fabrice Di Meglio            }
1307b492524403ca34b0cb03bfad6456909494479925Fabrice Di Meglio            if (oldVersion == 201) {
1308b492524403ca34b0cb03bfad6456909494479925Fabrice Di Meglio                upgradeToVersion202(db);
13092cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                createEventsView = true;
1310b492524403ca34b0cb03bfad6456909494479925Fabrice Di Meglio                oldVersion += 1;
1311b492524403ca34b0cb03bfad6456909494479925Fabrice Di Meglio            }
13127544af675ce2fd78f33198e5e9194f2bc7bd129fAndy McFadden            if (oldVersion == 202) {
13137544af675ce2fd78f33198e5e9194f2bc7bd129fAndy McFadden                if (need203Update) {
13147544af675ce2fd78f33198e5e9194f2bc7bd129fAndy McFadden                    upgradeToVersion203(db);
13157544af675ce2fd78f33198e5e9194f2bc7bd129fAndy McFadden                }
1316315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio                oldVersion += 1;
1317315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio            }
1318c4d44fd028e7f5f44f46439c3410dab3456e6d3fFabrice Di Meglio            if (oldVersion == 203) {
13192cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                createEventsView = true;
1320c4d44fd028e7f5f44f46439c3410dab3456e6d3fFabrice Di Meglio                oldVersion += 1;
1321c4d44fd028e7f5f44f46439c3410dab3456e6d3fFabrice Di Meglio            }
13227544af675ce2fd78f33198e5e9194f2bc7bd129fAndy McFadden            if (oldVersion == 206) {
13237544af675ce2fd78f33198e5e9194f2bc7bd129fAndy McFadden                // v206 exists only in HC (change Event._id to autoincrement).  Otherwise
13247544af675ce2fd78f33198e5e9194f2bc7bd129fAndy McFadden                // identical to v204, so back it up and let the upgrade path continue.
13257544af675ce2fd78f33198e5e9194f2bc7bd129fAndy McFadden                oldVersion -= 2;
13267544af675ce2fd78f33198e5e9194f2bc7bd129fAndy McFadden            }
13274067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden            if (oldVersion == 204) {
1328c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                // This is an ICS update, all following use 300+ versions.
13294067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                upgradeToVersion205(db);
13304067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                createEventsView = true;
13314067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                oldVersion += 1;
13324067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden            }
1333c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik            if (oldVersion == 205) {
1334c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                // Move ICS updates to 300 range
1335c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                upgradeToVersion300(db);
1336c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                createEventsView = true;
1337c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                oldVersion = 300;
1338c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik            }
133934c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik            if (oldVersion == 300) {
134034c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik                upgradeToVersion301(db);
134134c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik                createEventsView = true;
134234c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik                oldVersion++;
134334c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik            }
1344da641c374b00946f37bfe00e53bb292f4e0103d8RoboErik            if (oldVersion == 301) {
1345da641c374b00946f37bfe00e53bb292f4e0103d8RoboErik                upgradeToVersion302(db);
1346da641c374b00946f37bfe00e53bb292f4e0103d8RoboErik                oldVersion++;
1347da641c374b00946f37bfe00e53bb292f4e0103d8RoboErik            }
1348fa332ecedc0c340109811552407142f6e4f600b2RoboErik            if (oldVersion == 302) {
1349fa332ecedc0c340109811552407142f6e4f600b2RoboErik                upgradeToVersion303(db);
1350fa332ecedc0c340109811552407142f6e4f600b2RoboErik                oldVersion++;
1351fa332ecedc0c340109811552407142f6e4f600b2RoboErik                createEventsView = true;
1352fa332ecedc0c340109811552407142f6e4f600b2RoboErik            }
13539ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert            if (oldVersion == 303) {
13549ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                upgradeToVersion304(db);
13559ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                oldVersion++;
13569ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                createEventsView = true;
13579ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert            }
135802f97c538fc46a08d857d2c807c76fd0eec12493RoboErik            if (oldVersion == 304) {
135902f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                upgradeToVersion305(db);
136002f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                oldVersion++;
136102f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                createEventsView = true;
136202f97c538fc46a08d857d2c807c76fd0eec12493RoboErik            }
1363470aa5bc291ca33d51dda356f38ac2954026da9aAlon Albert            if (oldVersion == 305) {
1364470aa5bc291ca33d51dda356f38ac2954026da9aAlon Albert                upgradeToVersion306(db);
1365470aa5bc291ca33d51dda356f38ac2954026da9aAlon Albert                // force a sync to update edit url and etag
1366470aa5bc291ca33d51dda356f38ac2954026da9aAlon Albert                scheduleSync(null /* all accounts */, false, null);
1367470aa5bc291ca33d51dda356f38ac2954026da9aAlon Albert                oldVersion++;
1368470aa5bc291ca33d51dda356f38ac2954026da9aAlon Albert            }
1369935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            if (oldVersion == 306) {
1370935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden                upgradeToVersion307(db);
1371935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden                oldVersion++;
1372935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            }
13732f251c778c06d21ed7693a70f4a1268ff929242eRoboErik            if (oldVersion == 307) {
13742f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                upgradeToVersion308(db);
13752f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                oldVersion++;
13762f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                createEventsView = true;
13772f251c778c06d21ed7693a70f4a1268ff929242eRoboErik            }
1378c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert            if (oldVersion == 308) {
1379ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson                upgradeToVersion400(db);
1380c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                createEventsView = true;
1381ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson                oldVersion = 400;
1382ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson            }
1383ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson            // 309 was changed to 400 since it is the first change of the J release.
1384ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson            if (oldVersion == 309 || oldVersion == 400) {
1385ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson                upgradeToVersion401(db);
1386ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson                createEventsView = true;
1387ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson                oldVersion = 401;
1388c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert            }
1389bafe9de156292f65b1079dd1eb586669f573d9e6Michael Chan            if (oldVersion == 401) {
1390bafe9de156292f65b1079dd1eb586669f573d9e6Michael Chan                upgradeToVersion402(db);
1391bafe9de156292f65b1079dd1eb586669f573d9e6Michael Chan                createEventsView = true;
1392bafe9de156292f65b1079dd1eb586669f573d9e6Michael Chan                oldVersion = 402;
1393bafe9de156292f65b1079dd1eb586669f573d9e6Michael Chan            }
1394c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan            if (oldVersion == 402) {
1395c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan                upgradeToVersion403(db);
1396501e60bcb1b519d80723f7b64ba60bd079b8ec8dSara Ting                createEventsView = true;
1397c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan                oldVersion = 403;
1398c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan            }
1399b2695bf3cfb173c4c5ba7bfd3c93ba8a51d65810Alon Albert            if (oldVersion == 403) {
1400b2695bf3cfb173c4c5ba7bfd3c93ba8a51d65810Alon Albert                upgradeToVersion501(db);
1401501e60bcb1b519d80723f7b64ba60bd079b8ec8dSara Ting                createEventsView = true;
1402b2695bf3cfb173c4c5ba7bfd3c93ba8a51d65810Alon Albert                oldVersion = 501;
1403b2695bf3cfb173c4c5ba7bfd3c93ba8a51d65810Alon Albert            }
1404501e60bcb1b519d80723f7b64ba60bd079b8ec8dSara Ting            if (oldVersion == 501) {
1405501e60bcb1b519d80723f7b64ba60bd079b8ec8dSara Ting                upgradeToVersion502(db);
1406501e60bcb1b519d80723f7b64ba60bd079b8ec8dSara Ting                createEventsView = true; // This is needed if the calendars or events schema changed
1407501e60bcb1b519d80723f7b64ba60bd079b8ec8dSara Ting                oldVersion = 502;
1408501e60bcb1b519d80723f7b64ba60bd079b8ec8dSara Ting            }
14097a2531a4b68e9efe14353cc7f4a64a8c5613e5d3Alon Albert            if (oldVersion < 600) {
14107a2531a4b68e9efe14353cc7f4a64a8c5613e5d3Alon Albert                upgradeToVersion600(db);
14117a2531a4b68e9efe14353cc7f4a64a8c5613e5d3Alon Albert                createEventsView = true; // This is needed if the calendars or events schema changed
14127a2531a4b68e9efe14353cc7f4a64a8c5613e5d3Alon Albert                oldVersion = 600;
14137a2531a4b68e9efe14353cc7f4a64a8c5613e5d3Alon Albert            }
1414b2695bf3cfb173c4c5ba7bfd3c93ba8a51d65810Alon Albert
14152cff10f1a005bd7302245d4c680cf851193c3a97RoboErik            if (createEventsView) {
14162cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                createEventsView(db);
14172cff10f1a005bd7302245d4c680cf851193c3a97RoboErik            }
1418b492524403ca34b0cb03bfad6456909494479925Fabrice Di Meglio            if (oldVersion != DATABASE_VERSION) {
1419b492524403ca34b0cb03bfad6456909494479925Fabrice Di Meglio                Log.e(TAG, "Need to recreate Calendar schema because of "
1420b492524403ca34b0cb03bfad6456909494479925Fabrice Di Meglio                        + "unknown Calendar database version: " + oldVersion);
1421b492524403ca34b0cb03bfad6456909494479925Fabrice Di Meglio                dropTables(db);
1422b492524403ca34b0cb03bfad6456909494479925Fabrice Di Meglio                bootstrapDB(db);
1423b492524403ca34b0cb03bfad6456909494479925Fabrice Di Meglio                oldVersion = DATABASE_VERSION;
1424935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            } else {
1425935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden                removeOrphans(db);
1426b492524403ca34b0cb03bfad6456909494479925Fabrice Di Meglio            }
1427a6357118c223d00ed722ecd40ecdda92d705d211Erik        } catch (SQLiteException e) {
1428c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan            if (mInTestMode) {
1429c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan                // We do want to crash if we are in test mode.
1430c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan                throw e;
1431c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan            }
14327544af675ce2fd78f33198e5e9194f2bc7bd129fAndy McFadden            Log.e(TAG, "onUpgrade: SQLiteException, recreating db. ", e);
14337544af675ce2fd78f33198e5e9194f2bc7bd129fAndy McFadden            Log.e(TAG, "(oldVersion was " + oldVersion + ")");
1434a6357118c223d00ed722ecd40ecdda92d705d211Erik            dropTables(db);
1435a6357118c223d00ed722ecd40ecdda92d705d211Erik            bootstrapDB(db);
1436a6357118c223d00ed722ecd40ecdda92d705d211Erik            return; // this was lossy
1437bf897b03effb752368a98cfb89e6b90cfdde50fcMarc Blank        }
1438c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik
14397544af675ce2fd78f33198e5e9194f2bc7bd129fAndy McFadden        long endWhen = System.nanoTime();
14407544af675ce2fd78f33198e5e9194f2bc7bd129fAndy McFadden        Log.d(TAG, "Calendar upgrade took " + ((endWhen - startWhen) / 1000000) + "ms");
14417544af675ce2fd78f33198e5e9194f2bc7bd129fAndy McFadden
1442c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik        /**
1443c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik         * db versions < 100 correspond to Froyo and earlier. Gingerbread bumped
1444c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik         * the db versioning to 100. Honeycomb bumped it to 200. ICS will begin
1445c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik         * in 300. At each major release we should jump to the next
1446c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik         * centiversion.
1447c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik         */
1448ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff    }
1449ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff
14500d8699eedb0f3bcec1854b9753ae59154a122726Michael Chan    @Override
14510d8699eedb0f3bcec1854b9753ae59154a122726Michael Chan    public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
14520d8699eedb0f3bcec1854b9753ae59154a122726Michael Chan        Log.i(TAG, "Can't downgrade DB from version " + oldVersion + " to " + newVersion);
14530d8699eedb0f3bcec1854b9753ae59154a122726Michael Chan        dropTables(db);
14540d8699eedb0f3bcec1854b9753ae59154a122726Michael Chan        bootstrapDB(db);
14550d8699eedb0f3bcec1854b9753ae59154a122726Michael Chan        return;
14560d8699eedb0f3bcec1854b9753ae59154a122726Michael Chan    }
14570d8699eedb0f3bcec1854b9753ae59154a122726Michael Chan
14581599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio    /**
1459679d544f38aa33d00c12884b987d8f8af2a6a6d3Fabrice Di Meglio     * If the user_version of the database if between 59 and 66 (those versions has been deployed
1460679d544f38aa33d00c12884b987d8f8af2a6a6d3Fabrice Di Meglio     * with no primary key for the CalendarMetaData table)
14611599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio     */
14622cff10f1a005bd7302245d4c680cf851193c3a97RoboErik    private void recreateMetaDataAndInstances67(SQLiteDatabase db) {
1463679d544f38aa33d00c12884b987d8f8af2a6a6d3Fabrice Di Meglio        // Recreate the CalendarMetaData table with correct primary key
14642cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("DROP TABLE CalendarMetaData;");
14652cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        createCalendarMetaDataTable59(db);
1466679d544f38aa33d00c12884b987d8f8af2a6a6d3Fabrice Di Meglio
1467679d544f38aa33d00c12884b987d8f8af2a6a6d3Fabrice Di Meglio        // Also clean the Instance table as this table may be corrupted
14682cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("DELETE FROM Instances;");
1469ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff    }
1470ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff
14717b40dde3168f4af2c757cb43955aa3bfe1668666Erik    private static boolean fixAllDayTime(Time time, String timezone, Long timeInMillis) {
14727b40dde3168f4af2c757cb43955aa3bfe1668666Erik        time.set(timeInMillis);
14737b40dde3168f4af2c757cb43955aa3bfe1668666Erik        if(time.hour != 0 || time.minute != 0 || time.second != 0) {
14747b40dde3168f4af2c757cb43955aa3bfe1668666Erik            time.hour = 0;
14757b40dde3168f4af2c757cb43955aa3bfe1668666Erik            time.minute = 0;
14767b40dde3168f4af2c757cb43955aa3bfe1668666Erik            time.second = 0;
14777b40dde3168f4af2c757cb43955aa3bfe1668666Erik            return true;
14787b40dde3168f4af2c757cb43955aa3bfe1668666Erik        }
14797b40dde3168f4af2c757cb43955aa3bfe1668666Erik        return false;
14807b40dde3168f4af2c757cb43955aa3bfe1668666Erik    }
14817b40dde3168f4af2c757cb43955aa3bfe1668666Erik
1482ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson    /**********************************************************/
1483ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson    /* DO NOT USE CONSTANTS FOR UPGRADES, USE STRING LITERALS */
1484ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson    /**********************************************************/
1485ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson
1486ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson    /**********************************************************/
1487b2695bf3cfb173c4c5ba7bfd3c93ba8a51d65810Alon Albert    /* 6xx db version is for K release
1488b2695bf3cfb173c4c5ba7bfd3c93ba8a51d65810Alon Albert    /**********************************************************/
1489b2695bf3cfb173c4c5ba7bfd3c93ba8a51d65810Alon Albert
14907a2531a4b68e9efe14353cc7f4a64a8c5613e5d3Alon Albert    private void upgradeToVersion600(SQLiteDatabase db) {
14917a2531a4b68e9efe14353cc7f4a64a8c5613e5d3Alon Albert        /*
14927a2531a4b68e9efe14353cc7f4a64a8c5613e5d3Alon Albert         * Changes from version 5xx to 600:
14937a2531a4b68e9efe14353cc7f4a64a8c5613e5d3Alon Albert         * - add mutator columns to Events & calendars
14947a2531a4b68e9efe14353cc7f4a64a8c5613e5d3Alon Albert         */
14957a2531a4b68e9efe14353cc7f4a64a8c5613e5d3Alon Albert        db.execSQL("ALTER TABLE Events ADD COLUMN mutators TEXT;");
14967a2531a4b68e9efe14353cc7f4a64a8c5613e5d3Alon Albert        db.execSQL("ALTER TABLE Calendars ADD COLUMN mutators TEXT;");
14977a2531a4b68e9efe14353cc7f4a64a8c5613e5d3Alon Albert    }
14987a2531a4b68e9efe14353cc7f4a64a8c5613e5d3Alon Albert
1499b2695bf3cfb173c4c5ba7bfd3c93ba8a51d65810Alon Albert    /**********************************************************/
1500b2695bf3cfb173c4c5ba7bfd3c93ba8a51d65810Alon Albert    /* 5xx db version is for JB MR1 release
1501ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson    /**********************************************************/
1502ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson
1503b2695bf3cfb173c4c5ba7bfd3c93ba8a51d65810Alon Albert    private void upgradeToVersion501(SQLiteDatabase db) {
1504b2695bf3cfb173c4c5ba7bfd3c93ba8a51d65810Alon Albert        /*
1505b2695bf3cfb173c4c5ba7bfd3c93ba8a51d65810Alon Albert         * Changes from version 403 to 501:
1506b2695bf3cfb173c4c5ba7bfd3c93ba8a51d65810Alon Albert         * - add isOrganizer column to Events table
1507b2695bf3cfb173c4c5ba7bfd3c93ba8a51d65810Alon Albert         * - add isPrimary column to Calendars table
1508b2695bf3cfb173c4c5ba7bfd3c93ba8a51d65810Alon Albert         */
1509b2695bf3cfb173c4c5ba7bfd3c93ba8a51d65810Alon Albert        db.execSQL("ALTER TABLE Events ADD COLUMN isOrganizer INTEGER;");
1510b2695bf3cfb173c4c5ba7bfd3c93ba8a51d65810Alon Albert        db.execSQL("ALTER TABLE Calendars ADD COLUMN isPrimary INTEGER;");
1511b2695bf3cfb173c4c5ba7bfd3c93ba8a51d65810Alon Albert    }
1512b2695bf3cfb173c4c5ba7bfd3c93ba8a51d65810Alon Albert
1513501e60bcb1b519d80723f7b64ba60bd079b8ec8dSara Ting    private void upgradeToVersion502(SQLiteDatabase db) {
1514501e60bcb1b519d80723f7b64ba60bd079b8ec8dSara Ting        /*
1515501e60bcb1b519d80723f7b64ba60bd079b8ec8dSara Ting         * Changes from version 501 to 502:
1516501e60bcb1b519d80723f7b64ba60bd079b8ec8dSara Ting         * - add UID for events added from the RFC 2445 iCalendar format.
1517501e60bcb1b519d80723f7b64ba60bd079b8ec8dSara Ting         */
1518501e60bcb1b519d80723f7b64ba60bd079b8ec8dSara Ting        db.execSQL("ALTER TABLE Events ADD COLUMN uid2445 TEXT;");
1519501e60bcb1b519d80723f7b64ba60bd079b8ec8dSara Ting    }
1520501e60bcb1b519d80723f7b64ba60bd079b8ec8dSara Ting
1521ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson    /**********************************************************/
1522ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson    /* 4xx db version is for J release
1523ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson    /**********************************************************/
1524ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson
1525c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan    private void upgradeToVersion403(SQLiteDatabase db) {
1526c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan        /*
1527c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan         * Changes from version 402 to 403:
1528c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan         * - add custom app package name and uri Events table
1529c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan         */
1530c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan        db.execSQL("ALTER TABLE Events ADD COLUMN customAppPackage TEXT;");
1531c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan        db.execSQL("ALTER TABLE Events ADD COLUMN customAppUri TEXT;");
1532c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan    }
1533c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan
1534c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan    private void upgradeToVersion402(SQLiteDatabase db) {
1535bafe9de156292f65b1079dd1eb586669f573d9e6Michael Chan        /*
1536bafe9de156292f65b1079dd1eb586669f573d9e6Michael Chan         * Changes from version 401 to 402:
1537bafe9de156292f65b1079dd1eb586669f573d9e6Michael Chan         * - add identity and namespace to Attendees table
1538bafe9de156292f65b1079dd1eb586669f573d9e6Michael Chan         */
1539bafe9de156292f65b1079dd1eb586669f573d9e6Michael Chan        db.execSQL("ALTER TABLE Attendees ADD COLUMN attendeeIdentity TEXT;");
1540bafe9de156292f65b1079dd1eb586669f573d9e6Michael Chan        db.execSQL("ALTER TABLE Attendees ADD COLUMN attendeeIdNamespace TEXT;");
1541bafe9de156292f65b1079dd1eb586669f573d9e6Michael Chan    }
1542bafe9de156292f65b1079dd1eb586669f573d9e6Michael Chan
1543ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson    /*
1544ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson     * Changes from version 309 to 401:
1545ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson     * Fix repeating events' exceptions with the wrong original_id
1546ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson     */
1547ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson    private void upgradeToVersion401(SQLiteDatabase db) {
1548ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson        db.execSQL("UPDATE events SET original_id=(SELECT _id FROM events inner_events WHERE " +
1549ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson                "inner_events._sync_id=events.original_sync_id AND " +
1550ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson                "inner_events.calendar_id=events.calendar_id) WHERE NOT original_id IS NULL AND " +
1551ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson                "(SELECT calendar_id FROM events ex_events WHERE " +
1552ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson                "ex_events._id=events.original_id) <> calendar_id ");
1553ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson    }
1554ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson
1555ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson    private void upgradeToVersion400(SQLiteDatabase db) {
1556c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert        db.execSQL("DROP TRIGGER IF EXISTS calendar_color_update");
1557ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson        // CREATE_CALENDAR_COLOR_UPDATE_TRIGGER was inlined
1558ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson        db.execSQL("CREATE TRIGGER "
1559ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson                + "calendar_color_update" + " UPDATE OF " + Calendars.CALENDAR_COLOR_KEY
1560ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson                + " ON " + Tables.CALENDARS + " WHEN new." + Calendars.CALENDAR_COLOR_KEY
1561ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson                + " NOT NULL BEGIN " + "UPDATE " + Tables.CALENDARS
1562ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson                + " SET calendar_color=(SELECT " + Colors.COLOR + " FROM " + Tables.COLORS
1563ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson                + " WHERE " + Colors.ACCOUNT_NAME + "=" + "new." + Calendars.ACCOUNT_NAME + " AND "
1564ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson                + Colors.ACCOUNT_TYPE + "=" + "new." + Calendars.ACCOUNT_TYPE + " AND "
1565ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson                + Colors.COLOR_KEY + "=" + "new." + Calendars.CALENDAR_COLOR_KEY + " AND "
1566ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson                + Colors.COLOR_TYPE + "=" + Colors.TYPE_CALENDAR + ") "
1567ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson                + " WHERE " + Calendars._ID + "=" + "old." + Calendars._ID
1568ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson                + ";" + " END");
1569c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert        db.execSQL("DROP TRIGGER IF EXISTS event_color_update");
1570ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson        // CREATE_EVENT_COLOR_UPDATE_TRIGGER was inlined
1571ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson        db.execSQL("CREATE TRIGGER "
1572ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson                + "event_color_update" + " UPDATE OF " + Events.EVENT_COLOR_KEY + " ON "
1573ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson                + Tables.EVENTS + " WHEN new." + Events.EVENT_COLOR_KEY + " NOT NULL BEGIN "
1574ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson                + "UPDATE " + Tables.EVENTS
1575ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson                + " SET eventColor=(SELECT " + Colors.COLOR + " FROM " + Tables.COLORS + " WHERE "
1576ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson                + Colors.ACCOUNT_NAME + "=" + "(SELECT " + Calendars.ACCOUNT_NAME + " FROM "
1577ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson                + Tables.CALENDARS + " WHERE " + Calendars._ID + "=new." + Events.CALENDAR_ID
1578ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson                + ") AND " + Colors.ACCOUNT_TYPE + "=" + "(SELECT " + Calendars.ACCOUNT_TYPE
1579ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson                + " FROM " + Tables.CALENDARS + " WHERE " + Calendars._ID + "=new."
1580ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson                + Events.CALENDAR_ID + ") AND " + Colors.COLOR_KEY + "=" + "new."
1581ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson                + Events.EVENT_COLOR_KEY + " AND " + Colors.COLOR_TYPE + "="
1582ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson                + Colors.TYPE_EVENT + ") "
1583ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson                + " WHERE " + Events._ID + "=" + "old." + Events._ID + ";" + " END");
1584c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert    }
1585c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert
1586c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan    private void upgradeToVersion308(SQLiteDatabase db) {
15872f251c778c06d21ed7693a70f4a1268ff929242eRoboErik        /*
15882f251c778c06d21ed7693a70f4a1268ff929242eRoboErik         * Changes from version 307 to 308:
15892f251c778c06d21ed7693a70f4a1268ff929242eRoboErik         * - add Colors table to db
15902f251c778c06d21ed7693a70f4a1268ff929242eRoboErik         * - add eventColor_index to Events table
15912f251c778c06d21ed7693a70f4a1268ff929242eRoboErik         * - add calendar_color_index to Calendars table
15922f251c778c06d21ed7693a70f4a1268ff929242eRoboErik         * - add allowedAttendeeTypes to Calendars table
15932f251c778c06d21ed7693a70f4a1268ff929242eRoboErik         * - add allowedAvailability to Calendars table
15942f251c778c06d21ed7693a70f4a1268ff929242eRoboErik         */
15952f251c778c06d21ed7693a70f4a1268ff929242eRoboErik        createColorsTable(db);
15962f251c778c06d21ed7693a70f4a1268ff929242eRoboErik
15972f251c778c06d21ed7693a70f4a1268ff929242eRoboErik        db.execSQL("ALTER TABLE Calendars ADD COLUMN allowedAvailability TEXT DEFAULT '0,1';");
15982f251c778c06d21ed7693a70f4a1268ff929242eRoboErik        db.execSQL("ALTER TABLE Calendars ADD COLUMN allowedAttendeeTypes TEXT DEFAULT '0,1,2';");
15992f251c778c06d21ed7693a70f4a1268ff929242eRoboErik        db.execSQL("ALTER TABLE Calendars ADD COLUMN calendar_color_index TEXT;");
16002f251c778c06d21ed7693a70f4a1268ff929242eRoboErik        db.execSQL("ALTER TABLE Events ADD COLUMN eventColor_index TEXT;");
16012f251c778c06d21ed7693a70f4a1268ff929242eRoboErik
16022f251c778c06d21ed7693a70f4a1268ff929242eRoboErik        // Default Exchange calendars to be supporting the 'tentative'
16032f251c778c06d21ed7693a70f4a1268ff929242eRoboErik        // availability as well
16042f251c778c06d21ed7693a70f4a1268ff929242eRoboErik        db.execSQL("UPDATE Calendars SET allowedAvailability='0,1,2' WHERE _id IN "
16052f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "(SELECT _id FROM Calendars WHERE account_type='com.android.exchange');");
16062f251c778c06d21ed7693a70f4a1268ff929242eRoboErik
16072f251c778c06d21ed7693a70f4a1268ff929242eRoboErik        // Triggers to update the color stored in an event or a calendar when
16082f251c778c06d21ed7693a70f4a1268ff929242eRoboErik        // the color_index is changed.
16092f251c778c06d21ed7693a70f4a1268ff929242eRoboErik        createColorsTriggers(db);
16102f251c778c06d21ed7693a70f4a1268ff929242eRoboErik    }
16112f251c778c06d21ed7693a70f4a1268ff929242eRoboErik
1612c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan    private void upgradeToVersion307(SQLiteDatabase db) {
1613935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden        /*
1614935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden         * Changes from version 306 to 307:
1615935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden         * - Changed _id field to AUTOINCREMENT
1616935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden         */
1617935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden        db.execSQL("ALTER TABLE Events RENAME TO Events_Backup;");
1618935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden        db.execSQL("DROP TRIGGER IF EXISTS events_cleanup_delete");
1619935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden        db.execSQL("DROP TRIGGER IF EXISTS original_sync_update");
1620935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden        db.execSQL("DROP INDEX IF EXISTS eventsCalendarIdIndex");
16212f251c778c06d21ed7693a70f4a1268ff929242eRoboErik        createEventsTable307(db);
1622935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden
1623935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden        String FIELD_LIST =
1624935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "_id, " +
1625935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "_sync_id, " +
1626935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "dirty, " +
1627935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "lastSynced," +
1628935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "calendar_id, " +
1629935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "title, " +
1630935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "eventLocation, " +
1631935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "description, " +
1632935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "eventColor, " +
1633935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "eventStatus, " +
1634935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "selfAttendeeStatus, " +
1635935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "dtstart, " +
1636935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "dtend, " +
1637935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "eventTimezone, " +
1638935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "duration, " +
1639935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "allDay, " +
1640935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "accessLevel, " +
1641935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "availability, " +
1642935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "hasAlarm, " +
1643935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "hasExtendedProperties, " +
1644935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "rrule, " +
1645935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "rdate, " +
1646935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "exrule, " +
1647935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "exdate, " +
1648935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "original_id," +
1649935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "original_sync_id, " +
1650935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "originalInstanceTime, " +
1651935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "originalAllDay, " +
1652935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "lastDate, " +
1653935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "hasAttendeeData, " +
1654935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "guestsCanModify, " +
1655935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "guestsCanInviteOthers, " +
1656935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "guestsCanSeeGuests, " +
1657935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "organizer, " +
1658935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "deleted, " +
1659935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "eventEndTimezone, " +
1660935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "sync_data1," +
1661935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "sync_data2," +
1662935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "sync_data3," +
1663935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "sync_data4," +
1664935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "sync_data5," +
1665935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "sync_data6," +
1666935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "sync_data7," +
1667935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "sync_data8," +
1668935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "sync_data9," +
1669935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "sync_data10 ";
1670935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden
1671935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden        // copy fields from old to new
1672935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden        db.execSQL("INSERT INTO Events (" + FIELD_LIST + ") SELECT " + FIELD_LIST +
1673935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden                "FROM Events_Backup;");
1674935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden
1675935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden        db.execSQL("DROP TABLE Events_Backup;");
1676935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden
1677935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden        // Trigger to remove data tied to an event when we delete that event.
1678935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden        db.execSQL("CREATE TRIGGER events_cleanup_delete DELETE ON " + Tables.EVENTS + " " +
1679935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden                "BEGIN " + EVENTS_CLEANUP_TRIGGER_SQL + "END");
1680935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden
1681935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden        // Trigger to update exceptions when an original event updates its
1682935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden        // _sync_id
1683935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden        db.execSQL(CREATE_SYNC_ID_UPDATE_TRIGGER);
1684935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden    }
1685935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden
1686c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan    private void upgradeToVersion306(SQLiteDatabase db) {
1687470aa5bc291ca33d51dda356f38ac2954026da9aAlon Albert        /*
1688470aa5bc291ca33d51dda356f38ac2954026da9aAlon Albert        * The following changes are for google.com accounts only.
1689470aa5bc291ca33d51dda356f38ac2954026da9aAlon Albert        *
1690470aa5bc291ca33d51dda356f38ac2954026da9aAlon Albert        * Change event id's from ".../private/full/... to .../events/...
1691470aa5bc291ca33d51dda356f38ac2954026da9aAlon Albert        * Set Calendars.canPartiallyUpdate to 1 to support partial updates
1692470aa5bc291ca33d51dda356f38ac2954026da9aAlon Albert        * Nuke sync state so we re-sync with a fresh etag and edit url
16933ac8148cdc79bde4b009ccb6a9ffda77bdb547d3Andy McFadden        *
16943ac8148cdc79bde4b009ccb6a9ffda77bdb547d3Andy McFadden        * We need to drop the original_sync_update trigger because it fires whenever the
16953ac8148cdc79bde4b009ccb6a9ffda77bdb547d3Andy McFadden        * sync_id field is touched, and dramatically slows this operation.
1696470aa5bc291ca33d51dda356f38ac2954026da9aAlon Albert        */
16973ac8148cdc79bde4b009ccb6a9ffda77bdb547d3Andy McFadden        db.execSQL("DROP TRIGGER IF EXISTS original_sync_update");
1698470aa5bc291ca33d51dda356f38ac2954026da9aAlon Albert        db.execSQL("UPDATE Events SET "
1699470aa5bc291ca33d51dda356f38ac2954026da9aAlon Albert                + "_sync_id = REPLACE(_sync_id, '/private/full/', '/events/'), "
1700470aa5bc291ca33d51dda356f38ac2954026da9aAlon Albert                + "original_sync_id = REPLACE(original_sync_id, '/private/full/', '/events/') "
1701470aa5bc291ca33d51dda356f38ac2954026da9aAlon Albert                + "WHERE _id IN (SELECT Events._id FROM Events "
1702470aa5bc291ca33d51dda356f38ac2954026da9aAlon Albert                +    "JOIN Calendars ON Events.calendar_id = Calendars._id "
1703470aa5bc291ca33d51dda356f38ac2954026da9aAlon Albert                +    "WHERE account_type = 'com.google')"
1704470aa5bc291ca33d51dda356f38ac2954026da9aAlon Albert        );
17053ac8148cdc79bde4b009ccb6a9ffda77bdb547d3Andy McFadden        db.execSQL(CREATE_SYNC_ID_UPDATE_TRIGGER);
1706470aa5bc291ca33d51dda356f38ac2954026da9aAlon Albert
1707470aa5bc291ca33d51dda356f38ac2954026da9aAlon Albert        db.execSQL("UPDATE Calendars SET canPartiallyUpdate = 1 WHERE account_type = 'com.google'");
1708470aa5bc291ca33d51dda356f38ac2954026da9aAlon Albert
1709470aa5bc291ca33d51dda356f38ac2954026da9aAlon Albert        db.execSQL("DELETE FROM _sync_state WHERE account_type = 'com.google'");
1710470aa5bc291ca33d51dda356f38ac2954026da9aAlon Albert    }
1711470aa5bc291ca33d51dda356f38ac2954026da9aAlon Albert
1712c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan    private void upgradeToVersion305(SQLiteDatabase db) {
171302f97c538fc46a08d857d2c807c76fd0eec12493RoboErik        /*
171402f97c538fc46a08d857d2c807c76fd0eec12493RoboErik         * Changes from version 304 to 305:
171502f97c538fc46a08d857d2c807c76fd0eec12493RoboErik         * -Add CAL_SYNC columns up to 10
171602f97c538fc46a08d857d2c807c76fd0eec12493RoboErik         * -Rename Calendars.access_level to calendar_access_level
171702f97c538fc46a08d857d2c807c76fd0eec12493RoboErik         * -Rename calendars _sync_version to cal_sync7
171802f97c538fc46a08d857d2c807c76fd0eec12493RoboErik         * -Rename calendars _sync_time to cal_sync8
171902f97c538fc46a08d857d2c807c76fd0eec12493RoboErik         * -Rename displayName to calendar_displayName
172002f97c538fc46a08d857d2c807c76fd0eec12493RoboErik         * -Rename _sync_local_id to sync_data2
172102f97c538fc46a08d857d2c807c76fd0eec12493RoboErik         * -Rename htmlUri to sync_data3
172202f97c538fc46a08d857d2c807c76fd0eec12493RoboErik         * -Rename events _sync_version to sync_data4
172302f97c538fc46a08d857d2c807c76fd0eec12493RoboErik         * -Rename events _sync_time to sync_data5
172402f97c538fc46a08d857d2c807c76fd0eec12493RoboErik         * -Rename commentsUri to sync_data6
172502f97c538fc46a08d857d2c807c76fd0eec12493RoboErik         * -Migrate Events _sync_mark to sync_data8
172602f97c538fc46a08d857d2c807c76fd0eec12493RoboErik         * -Change sync_data2 from INTEGER to TEXT
172702f97c538fc46a08d857d2c807c76fd0eec12493RoboErik         * -Change sync_data8 from INTEGER to TEXT
172802f97c538fc46a08d857d2c807c76fd0eec12493RoboErik         * -Add SYNC_DATA columns up to 10
172902f97c538fc46a08d857d2c807c76fd0eec12493RoboErik         * -Add EVENT_COLOR to Events table
173002f97c538fc46a08d857d2c807c76fd0eec12493RoboErik         */
173102f97c538fc46a08d857d2c807c76fd0eec12493RoboErik
173202f97c538fc46a08d857d2c807c76fd0eec12493RoboErik        // rename old table, create new table with updated layout
173302f97c538fc46a08d857d2c807c76fd0eec12493RoboErik        db.execSQL("ALTER TABLE Calendars RENAME TO Calendars_Backup;");
173402f97c538fc46a08d857d2c807c76fd0eec12493RoboErik        db.execSQL("DROP TRIGGER IF EXISTS calendar_cleanup");
17352f251c778c06d21ed7693a70f4a1268ff929242eRoboErik        createCalendarsTable305(db);
173602f97c538fc46a08d857d2c807c76fd0eec12493RoboErik
173702f97c538fc46a08d857d2c807c76fd0eec12493RoboErik        // copy fields from old to new
173802f97c538fc46a08d857d2c807c76fd0eec12493RoboErik        db.execSQL("INSERT INTO Calendars (" +
173902f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "_id, " +
174002f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "account_name, " +
174102f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "account_type, " +
174202f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "_sync_id, " +
174302f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "cal_sync7, " +             // rename from _sync_version
174402f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "cal_sync8, " +             // rename from _sync_time
174502f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "dirty, " +
174602f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "name, " +
174702f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "calendar_displayName, " +  // rename from displayName
174802f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "calendar_color, " +
174902f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "calendar_access_level, " + // rename from access_level
175002f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "visible, " +
175102f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "sync_events, " +
175202f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "calendar_location, " +
175302f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "calendar_timezone, " +
175402f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "ownerAccount, " +
175502f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "canOrganizerRespond, " +
175602f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "canModifyTimeZone, " +
175702f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "maxReminders, " +
175802f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "allowedReminders, " +
175902f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "deleted, " +
176002f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "canPartiallyUpdate," +
176102f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "cal_sync1, " +
176202f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "cal_sync2, " +
176302f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "cal_sync3, " +
176402f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "cal_sync4, " +
176502f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "cal_sync5, " +
176602f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "cal_sync6) " +
176702f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "SELECT " +
176802f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "_id, " +
176902f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "account_name, " +
177002f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "account_type, " +
177102f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "_sync_id, " +
177202f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "_sync_version, " +
177302f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "_sync_time, " +
177402f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "dirty, " +
177502f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "name, " +
177602f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "displayName, " +
177702f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "calendar_color, " +
177802f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "access_level, " +
177902f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "visible, " +
178002f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "sync_events, " +
178102f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "calendar_location, " +
178202f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "calendar_timezone, " +
178302f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "ownerAccount, " +
178402f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "canOrganizerRespond, " +
178502f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "canModifyTimeZone, " +
178602f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "maxReminders, " +
178702f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "allowedReminders, " +
178802f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "deleted, " +
178902f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "canPartiallyUpdate," +
179002f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "cal_sync1, " +
179102f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "cal_sync2, " +
179202f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "cal_sync3, " +
179302f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "cal_sync4, " +
179402f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "cal_sync5, " +
179502f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "cal_sync6 " +
179602f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "FROM Calendars_Backup;");
179702f97c538fc46a08d857d2c807c76fd0eec12493RoboErik
179802f97c538fc46a08d857d2c807c76fd0eec12493RoboErik        // drop the old table
179902f97c538fc46a08d857d2c807c76fd0eec12493RoboErik        db.execSQL("DROP TABLE Calendars_Backup;");
180002f97c538fc46a08d857d2c807c76fd0eec12493RoboErik
180102f97c538fc46a08d857d2c807c76fd0eec12493RoboErik        db.execSQL("ALTER TABLE Events RENAME TO Events_Backup;");
180202f97c538fc46a08d857d2c807c76fd0eec12493RoboErik        db.execSQL("DROP TRIGGER IF EXISTS events_cleanup_delete");
180302f97c538fc46a08d857d2c807c76fd0eec12493RoboErik        db.execSQL("DROP INDEX IF EXISTS eventsCalendarIdIndex");
1804935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden        // 305 and 307 can share the same createEventsTable implementation, because the
1805935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden        // addition of "autoincrement" to _ID doesn't affect the upgrade path.  (Note that
1806935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden        // much older databases may also already have autoincrement set because the change
1807935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden        // was back-ported.)
18082f251c778c06d21ed7693a70f4a1268ff929242eRoboErik        createEventsTable307(db);
180902f97c538fc46a08d857d2c807c76fd0eec12493RoboErik
181002f97c538fc46a08d857d2c807c76fd0eec12493RoboErik        // copy fields from old to new
181102f97c538fc46a08d857d2c807c76fd0eec12493RoboErik        db.execSQL("INSERT INTO Events (" +
181202f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "_id, " +
181302f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "_sync_id, " +
181402f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "sync_data4, " +        // renamed from _sync_version
181502f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "sync_data5, " +        // renamed from _sync_time
181602f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "sync_data2, " +        // renamed from _sync_local_id
181702f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "dirty, " +
181802f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "sync_data8, " +        // renamed from _sync_mark
181902f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "calendar_id, " +
182002f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "sync_data3, " +        // renamed from htmlUri
182102f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "title, " +
182202f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "eventLocation, " +
182302f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "description, " +
182402f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "eventStatus, " +
182502f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "selfAttendeeStatus, " +
182602f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "sync_data6, " +        // renamed from commentsUri
182702f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "dtstart, " +
182802f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "dtend, " +
182902f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "eventTimezone, " +
183002f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "eventEndTimezone, " +
183102f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "duration, " +
183202f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "allDay, " +
183302f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "accessLevel, " +
183402f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "availability, " +
183502f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "hasAlarm, " +
183602f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "hasExtendedProperties, " +
183702f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "rrule, " +
183802f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "rdate, " +
183902f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "exrule, " +
184002f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "exdate, " +
184102f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "original_id," +
184202f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "original_sync_id, " +
184302f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "originalInstanceTime, " +
184402f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "originalAllDay, " +
184502f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "lastDate, " +
184602f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "hasAttendeeData, " +
184702f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "guestsCanModify, " +
184802f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "guestsCanInviteOthers, " +
184902f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "guestsCanSeeGuests, " +
185002f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "organizer, " +
185102f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "deleted, " +
185202f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "sync_data7," +
185302f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "lastSynced," +
185402f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "sync_data1) " +
185502f97c538fc46a08d857d2c807c76fd0eec12493RoboErik
185602f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "SELECT " +
185702f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "_id, " +
185802f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "_sync_id, " +
185902f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "_sync_version, " +
186002f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "_sync_time, " +
186102f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "_sync_local_id, " +
186202f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "dirty, " +
186302f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "_sync_mark, " +
186402f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "calendar_id, " +
186502f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "htmlUri, " +
186602f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "title, " +
186702f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "eventLocation, " +
186802f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "description, " +
186902f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "eventStatus, " +
187002f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "selfAttendeeStatus, " +
187102f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "commentsUri, " +
187202f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "dtstart, " +
187302f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "dtend, " +
187402f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "eventTimezone, " +
187502f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "eventEndTimezone, " +
187602f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "duration, " +
187702f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "allDay, " +
187802f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "accessLevel, " +
187902f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "availability, " +
188002f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "hasAlarm, " +
188102f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "hasExtendedProperties, " +
188202f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "rrule, " +
188302f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "rdate, " +
188402f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "exrule, " +
188502f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "exdate, " +
188602f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "original_id," +
188702f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "original_sync_id, " +
188802f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "originalInstanceTime, " +
188902f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "originalAllDay, " +
189002f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "lastDate, " +
189102f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "hasAttendeeData, " +
189202f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "guestsCanModify, " +
189302f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "guestsCanInviteOthers, " +
189402f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "guestsCanSeeGuests, " +
189502f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "organizer, " +
189602f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "deleted, " +
189702f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "sync_data7," +
189802f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "lastSynced," +
189902f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "sync_data1 " +
190002f97c538fc46a08d857d2c807c76fd0eec12493RoboErik
190102f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "FROM Events_Backup;"
190202f97c538fc46a08d857d2c807c76fd0eec12493RoboErik        );
190302f97c538fc46a08d857d2c807c76fd0eec12493RoboErik
190402f97c538fc46a08d857d2c807c76fd0eec12493RoboErik        db.execSQL("DROP TABLE Events_Backup;");
190502f97c538fc46a08d857d2c807c76fd0eec12493RoboErik
190602f97c538fc46a08d857d2c807c76fd0eec12493RoboErik        // Trigger to remove data tied to an event when we delete that event.
190702f97c538fc46a08d857d2c807c76fd0eec12493RoboErik        db.execSQL("CREATE TRIGGER events_cleanup_delete DELETE ON " + Tables.EVENTS + " " +
190802f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "BEGIN " +
190902f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                EVENTS_CLEANUP_TRIGGER_SQL +
191002f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "END");
191102f97c538fc46a08d857d2c807c76fd0eec12493RoboErik
191202f97c538fc46a08d857d2c807c76fd0eec12493RoboErik        // Trigger to update exceptions when an original event updates its
191302f97c538fc46a08d857d2c807c76fd0eec12493RoboErik        // _sync_id
191402f97c538fc46a08d857d2c807c76fd0eec12493RoboErik        db.execSQL(CREATE_SYNC_ID_UPDATE_TRIGGER);
191502f97c538fc46a08d857d2c807c76fd0eec12493RoboErik    }
191602f97c538fc46a08d857d2c807c76fd0eec12493RoboErik
1917c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan    private void upgradeToVersion304(SQLiteDatabase db) {
19189ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert        /*
19199ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert         * Changes from version 303 to 304:
19209ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert         * - add canPartiallyUpdate to Calendars table
19219ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert         * - add sync_data7 to Calendars to Events table
19229ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert         * - add lastSynced to Calendars to Events table
19239ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert         */
19249ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert        db.execSQL("ALTER TABLE Calendars ADD COLUMN canPartiallyUpdate INTEGER DEFAULT 0;");
19259ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert        db.execSQL("ALTER TABLE Events ADD COLUMN sync_data7 TEXT;");
19269ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert        db.execSQL("ALTER TABLE Events ADD COLUMN lastSynced INTEGER DEFAULT 0;");
19279ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert    }
19289ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert
1929c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan    private void upgradeToVersion303(SQLiteDatabase db) {
1930fa332ecedc0c340109811552407142f6e4f600b2RoboErik        /*
1931fa332ecedc0c340109811552407142f6e4f600b2RoboErik         * Changes from version 302 to 303:
1932fa332ecedc0c340109811552407142f6e4f600b2RoboErik         * - change SYNCx columns to CAL_SYNCx
1933fa332ecedc0c340109811552407142f6e4f600b2RoboErik         */
1934fa332ecedc0c340109811552407142f6e4f600b2RoboErik
1935fa332ecedc0c340109811552407142f6e4f600b2RoboErik        // rename old table, create new table with updated layout
1936fa332ecedc0c340109811552407142f6e4f600b2RoboErik        db.execSQL("ALTER TABLE Calendars RENAME TO Calendars_Backup;");
1937fa332ecedc0c340109811552407142f6e4f600b2RoboErik        db.execSQL("DROP TRIGGER IF EXISTS calendar_cleanup");
19389ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert        createCalendarsTable303(db);
1939fa332ecedc0c340109811552407142f6e4f600b2RoboErik
1940fa332ecedc0c340109811552407142f6e4f600b2RoboErik        // copy fields from old to new
1941fa332ecedc0c340109811552407142f6e4f600b2RoboErik        db.execSQL("INSERT INTO Calendars (" +
1942fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "_id, " +
1943fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "account_name, " +
1944fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "account_type, " +
1945fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "_sync_id, " +
1946fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "_sync_version, " +
1947fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "_sync_time, " +
1948fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "dirty, " +
1949fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "name, " +
1950fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "displayName, " +
1951fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "calendar_color, " +
1952fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "access_level, " +
1953fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "visible, " +
1954fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "sync_events, " +
1955fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "calendar_location, " +
1956fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "calendar_timezone, " +
1957fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "ownerAccount, " +
1958fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "canOrganizerRespond, " +
1959fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "canModifyTimeZone, " +
1960fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "maxReminders, " +
1961fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "allowedReminders, " +
1962fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "deleted, " +
1963fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "cal_sync1, " +     // rename from sync1
1964fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "cal_sync2, " +     // rename from sync2
1965fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "cal_sync3, " +     // rename from sync3
1966fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "cal_sync4, " +     // rename from sync4
1967fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "cal_sync5, " +     // rename from sync5
1968fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "cal_sync6) " +     // rename from sync6
1969fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "SELECT " +
1970fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "_id, " +
1971fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "account_name, " +
1972fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "account_type, " +
1973fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "_sync_id, " +
1974fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "_sync_version, " +
1975fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "_sync_time, " +
1976fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "dirty, " +
1977fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "name, " +
1978fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "displayName, " +
1979fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "calendar_color, " +
1980fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "access_level, " +
1981fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "visible, " +
1982fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "sync_events, " +
1983fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "calendar_location, " +
1984fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "calendar_timezone, " +
1985fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "ownerAccount, " +
1986fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "canOrganizerRespond, " +
1987fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "canModifyTimeZone, " +
1988fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "maxReminders, " +
1989fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "allowedReminders," +
1990fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "deleted, " +
1991fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "sync1, " +
1992fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "sync2, " +
1993fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "sync3, " +
1994fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "sync4," +
1995fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "sync5," +
1996fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "sync6 " +
1997fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "FROM Calendars_Backup;"
1998fa332ecedc0c340109811552407142f6e4f600b2RoboErik        );
1999fa332ecedc0c340109811552407142f6e4f600b2RoboErik
2000fa332ecedc0c340109811552407142f6e4f600b2RoboErik        // drop the old table
2001fa332ecedc0c340109811552407142f6e4f600b2RoboErik        db.execSQL("DROP TABLE Calendars_Backup;");
2002fa332ecedc0c340109811552407142f6e4f600b2RoboErik    }
2003fa332ecedc0c340109811552407142f6e4f600b2RoboErik
2004c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan    private void upgradeToVersion302(SQLiteDatabase db) {
2005da641c374b00946f37bfe00e53bb292f4e0103d8RoboErik        /*
2006da641c374b00946f37bfe00e53bb292f4e0103d8RoboErik         * Changes from version 301 to 302
2007da641c374b00946f37bfe00e53bb292f4e0103d8RoboErik         * - Move Exchange eventEndTimezone values to SYNC_DATA1
2008da641c374b00946f37bfe00e53bb292f4e0103d8RoboErik         */
2009da641c374b00946f37bfe00e53bb292f4e0103d8RoboErik        db.execSQL("UPDATE Events SET sync_data1=eventEndTimezone WHERE calendar_id IN "
2010da641c374b00946f37bfe00e53bb292f4e0103d8RoboErik                + "(SELECT _id FROM Calendars WHERE account_type='com.android.exchange');");
2011da641c374b00946f37bfe00e53bb292f4e0103d8RoboErik
2012da641c374b00946f37bfe00e53bb292f4e0103d8RoboErik        db.execSQL("UPDATE Events SET eventEndTimezone=NULL WHERE calendar_id IN "
2013da641c374b00946f37bfe00e53bb292f4e0103d8RoboErik                + "(SELECT _id FROM Calendars WHERE account_type='com.android.exchange');");
2014da641c374b00946f37bfe00e53bb292f4e0103d8RoboErik    }
2015da641c374b00946f37bfe00e53bb292f4e0103d8RoboErik
2016c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan    private void upgradeToVersion301(SQLiteDatabase db) {
201734c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik        /*
201834c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik         * Changes from version 300 to 301
201934c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik         * - Added original_id column to Events table
202034c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik         * - Added triggers to keep original_id and original_sync_id in sync
202134c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik         */
202234c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik
202334c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik        db.execSQL("DROP TRIGGER IF EXISTS " + SYNC_ID_UPDATE_TRIGGER_NAME + ";");
202434c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik
202534c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik        db.execSQL("ALTER TABLE Events ADD COLUMN original_id INTEGER;");
202634c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik
202734c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik        // Fill in the original_id for all events that have an original_sync_id
202834c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik        db.execSQL("UPDATE Events set original_id=" +
202934c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik                "(SELECT Events2._id FROM Events AS Events2 " +
203034c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik                        "WHERE Events2._sync_id=Events.original_sync_id) " +
203134c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik                "WHERE Events.original_sync_id NOT NULL");
203234c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik        // Trigger to update exceptions when an original event updates its
203334c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik        // _sync_id
203434c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik        db.execSQL(CREATE_SYNC_ID_UPDATE_TRIGGER);
203534c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik    }
203634c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik
2037c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan    private void upgradeToVersion300(SQLiteDatabase db) {
2038c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik
2039c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik        /*
2040c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik         * Changes from version 205 to 300:
2041c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik         * - rename _sync_account to account_name in Calendars table
2042c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik         * - remove _sync_account from Events table
2043c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik         * - rename _sync_account_type to account_type in Calendars table
2044c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik         * - remove _sync_account_type from Events table
2045c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik         * - rename _sync_dirty to dirty in Calendars/Events table
2046c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik         * - rename color to calendar_color in Calendars table
2047c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik         * - rename location to calendar_location in Calendars table
2048c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik         * - rename timezone to calendar_timezone in Calendars table
2049c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik         * - add allowedReminders in Calendars table
2050c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik         * - rename visibility to accessLevel in Events table
2051c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik         * - rename transparency to availability in Events table
2052c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik         * - rename originalEvent to original_sync_id in Events table
2053c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik         * - remove dtstart2 and dtend2 from Events table
2054c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik         * - rename syncAdapterData to sync_data1 in Events table
2055c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik         */
2056c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik
2057c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik        // rename old table, create new table with updated layout
2058c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik        db.execSQL("ALTER TABLE Calendars RENAME TO Calendars_Backup;");
205934c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik        db.execSQL("DROP TRIGGER IF EXISTS calendar_cleanup;");
2060fa332ecedc0c340109811552407142f6e4f600b2RoboErik        createCalendarsTable300(db);
2061c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik
2062c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik        // copy fields from old to new
2063c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik        db.execSQL("INSERT INTO Calendars (" +
2064c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "_id, " +
2065c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "account_name, " +          // rename from _sync_account
2066c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "account_type, " +          // rename from _sync_account_type
2067c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "_sync_id, " +
2068c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "_sync_version, " +
2069c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "_sync_time, " +
2070c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "dirty, " +                 // rename from _sync_dirty
2071c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "name, " +
2072c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "displayName, " +
2073c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "calendar_color, " +        // rename from color
2074c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "access_level, " +
2075c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "visible, " +
2076c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "sync_events, " +
2077c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "calendar_location, " +     // rename from location
2078c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "calendar_timezone, " +     // rename from timezone
2079c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "ownerAccount, " +
2080c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "canOrganizerRespond, " +
2081c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "canModifyTimeZone, " +
2082c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "maxReminders, " +
2083c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "allowedReminders," +
2084c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "deleted, " +
2085c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "sync1, " +
2086c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "sync2, " +
2087c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "sync3, " +
2088c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "sync4," +
2089c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "sync5," +
2090c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "sync6) " +
2091c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik
2092c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "SELECT " +
2093c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "_id, " +
2094c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "_sync_account, " +
2095c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "_sync_account_type, " +
2096c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "_sync_id, " +
2097c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "_sync_version, " +
2098c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "_sync_time, " +
2099c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "_sync_dirty, " +
2100c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "name, " +
2101c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "displayName, " +
2102c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "color, " +
2103c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "access_level, " +
2104c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "visible, " +
2105c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "sync_events, " +
2106c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "location, " +
2107c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "timezone, " +
2108c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "ownerAccount, " +
2109c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "canOrganizerRespond, " +
2110c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "canModifyTimeZone, " +
2111c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "maxReminders, " +
2112c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "'0,1,2,3'," +
2113c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "deleted, " +
2114c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "sync1, " +
2115c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "sync2, " +
2116c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "sync3, " +
2117c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "sync4, " +
2118c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "sync5, " +
2119c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "sync6 " +
2120c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "FROM Calendars_Backup;"
2121c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik        );
2122c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik
2123bf986d8deeeed9566e0badeba89d4800533cbca6Andy McFadden        /* expand the set of allowed reminders for Google calendars to include email */
2124bf986d8deeeed9566e0badeba89d4800533cbca6Andy McFadden        db.execSQL("UPDATE Calendars SET allowedReminders = '0,1,2' " +
2125bf986d8deeeed9566e0badeba89d4800533cbca6Andy McFadden                "WHERE account_type = 'com.google'");
2126bf986d8deeeed9566e0badeba89d4800533cbca6Andy McFadden
2127c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik        // drop the old table
2128c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik        db.execSQL("DROP TABLE Calendars_Backup;");
2129c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik
2130c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik        db.execSQL("ALTER TABLE Events RENAME TO Events_Backup;");
2131c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik        db.execSQL("DROP TRIGGER IF EXISTS events_insert");
2132c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik        db.execSQL("DROP TRIGGER IF EXISTS events_cleanup_delete");
2133c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik        db.execSQL("DROP INDEX IF EXISTS eventSyncAccountAndIdIndex");
2134c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik        db.execSQL("DROP INDEX IF EXISTS eventsCalendarIdIndex");
213534c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik        createEventsTable300(db);
2136c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik
2137c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik        // copy fields from old to new
2138c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik        db.execSQL("INSERT INTO Events (" +
2139c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "_id, " +
2140c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "_sync_id, " +
2141c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "_sync_version, " +
2142c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "_sync_time, " +
2143c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "_sync_local_id, " +
2144c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "dirty, " +                 // renamed from _sync_dirty
2145c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "_sync_mark, " +
2146c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "calendar_id, " +
2147c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "htmlUri, " +
2148c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "title, " +
2149c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "eventLocation, " +
2150c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "description, " +
2151c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "eventStatus, " +
2152c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "selfAttendeeStatus, " +
2153c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "commentsUri, " +
2154c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "dtstart, " +
2155c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "dtend, " +
2156c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "eventTimezone, " +
2157c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "eventEndTimezone, " +      // renamed from eventTimezone2
2158c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "duration, " +
2159c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "allDay, " +
2160c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "accessLevel, " +           // renamed from visibility
2161c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "availability, " +          // renamed from transparency
2162c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "hasAlarm, " +
2163c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "hasExtendedProperties, " +
2164c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "rrule, " +
2165c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "rdate, " +
2166c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "exrule, " +
2167c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "exdate, " +
2168c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "original_sync_id, " +      // renamed from originalEvent
2169c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "originalInstanceTime, " +
2170c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "originalAllDay, " +
2171c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "lastDate, " +
2172c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "hasAttendeeData, " +
2173c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "guestsCanModify, " +
2174c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "guestsCanInviteOthers, " +
2175c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "guestsCanSeeGuests, " +
2176c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "organizer, " +
2177c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "deleted, " +
2178c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "sync_data1) " +             // renamed from syncAdapterData
2179c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik
2180c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "SELECT " +
2181c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "_id, " +
2182c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "_sync_id, " +
2183c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "_sync_version, " +
2184c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "_sync_time, " +
2185c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "_sync_local_id, " +
2186c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "_sync_dirty, " +
2187c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "_sync_mark, " +
2188c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "calendar_id, " +
2189c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "htmlUri, " +
2190c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "title, " +
2191c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "eventLocation, " +
2192c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "description, " +
2193c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "eventStatus, " +
2194c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "selfAttendeeStatus, " +
2195c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "commentsUri, " +
2196c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "dtstart, " +
2197c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "dtend, " +
2198c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "eventTimezone, " +
2199c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "eventTimezone2, " +
2200c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "duration, " +
2201c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "allDay, " +
2202c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "visibility, " +
2203c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "transparency, " +
2204c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "hasAlarm, " +
2205c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "hasExtendedProperties, " +
2206c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "rrule, " +
2207c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "rdate, " +
2208c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "exrule, " +
2209c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "exdate, " +
2210c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "originalEvent, " +
2211c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "originalInstanceTime, " +
2212c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "originalAllDay, " +
2213c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "lastDate, " +
2214c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "hasAttendeeData, " +
2215c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "guestsCanModify, " +
2216c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "guestsCanInviteOthers, " +
2217c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "guestsCanSeeGuests, " +
2218c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "organizer, " +
2219c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "deleted, " +
2220c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "syncAdapterData " +
2221c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik
2222c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "FROM Events_Backup;"
2223c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik        );
2224c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik
2225c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik        db.execSQL("DROP TABLE Events_Backup;");
2226c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik
2227c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik        // Trigger to remove data tied to an event when we delete that event.
2228c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik        db.execSQL("CREATE TRIGGER events_cleanup_delete DELETE ON " + Tables.EVENTS + " " +
2229c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "BEGIN " +
2230c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                EVENTS_CLEANUP_TRIGGER_SQL +
2231c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "END");
2232c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik
2233fa332ecedc0c340109811552407142f6e4f600b2RoboErik    }
2234c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik
2235c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan    private void upgradeToVersion205(SQLiteDatabase db) {
22364067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden        /*
22374067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden         * Changes from version 204 to 205:
22384067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden         * - rename+reorder "_sync_mark" to "sync6" (and change type from INTEGER to TEXT)
22394067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden         * - rename "selected" to "visible"
22404067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden         * - rename "organizerCanRespond" to "canOrganizerRespond"
22414067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden         * - add "canModifyTimeZone"
22424067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden         * - add "maxReminders"
22434067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden         * - remove "_sync_local_id" (a/k/a _SYNC_DATA)
22444067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden         */
22454067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden
22464067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden        // rename old table, create new table with updated layout
22474067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden        db.execSQL("ALTER TABLE Calendars RENAME TO Calendars_Backup;");
22484067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden        db.execSQL("DROP TRIGGER IF EXISTS calendar_cleanup");
2249c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik        createCalendarsTable205(db);
22504067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden
22514067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden        // copy fields from old to new
22524067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden        db.execSQL("INSERT INTO Calendars (" +
22534067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "_id, " +
22544067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "_sync_account, " +
22554067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "_sync_account_type, " +
22564067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "_sync_id, " +
22574067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "_sync_version, " +
22584067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "_sync_time, " +
22594067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "_sync_dirty, " +
22604067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "name, " +
22614067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "displayName, " +
22624067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "color, " +
22634067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "access_level, " +
22644067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "visible, " +                   // rename from "selected"
22654067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "sync_events, " +
22664067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "location, " +
22674067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "timezone, " +
22684067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "ownerAccount, " +
22694067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "canOrganizerRespond, " +       // rename from "organizerCanRespond"
22704067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "canModifyTimeZone, " +
22714067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "maxReminders, " +
22724067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "deleted, " +
22734067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "sync1, " +
22744067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "sync2, " +
22754067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "sync3, " +
22764067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "sync4," +
22774067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "sync5," +
22784067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "sync6) " +                     // rename/reorder from _sync_mark
22794067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "SELECT " +
22804067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "_id, " +
22814067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "_sync_account, " +
22824067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "_sync_account_type, " +
22834067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "_sync_id, " +
22844067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "_sync_version, " +
22854067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "_sync_time, " +
22864067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "_sync_dirty, " +
22874067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "name, " +
22884067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "displayName, " +
22894067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "color, " +
22904067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "access_level, " +
22914067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "selected, " +
22924067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "sync_events, " +
22934067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "location, " +
22944067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "timezone, " +
22954067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "ownerAccount, " +
22964067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "organizerCanRespond, " +
22974067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "1, " +
22984067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "5, " +
22994067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "deleted, " +
23004067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "sync1, " +
23014067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "sync2, " +
23024067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "sync3, " +
23034067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "sync4, " +
23044067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "sync5, " +
23054067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "_sync_mark " +
23064067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "FROM Calendars_Backup;"
23074067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden        );
23084067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden
23094067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden        // set these fields appropriately for Exchange events
23104067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden        db.execSQL("UPDATE Calendars SET canModifyTimeZone=0, maxReminders=1 " +
23114067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "WHERE _sync_account_type='com.android.exchange'");
23124067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden
23134067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden        // drop the old table
23144067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden        db.execSQL("DROP TABLE Calendars_Backup;");
23154067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden    }
23164067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden
2317c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan    private void upgradeToVersion203(SQLiteDatabase db) {
2318315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        // Same as Gingerbread version 100
23192cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        Cursor cursor = db.rawQuery("SELECT value FROM CalendarCache WHERE key=?",
2320315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio                new String[] {"timezoneDatabaseVersion"});
2321315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio
2322315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        String oldTimezoneDbVersion = null;
23230332925aa9db8c4826327edd85030a4791b7a8e6Michael Chan        if (cursor != null) {
232458313767dd0e7e3823c35ca61b40eddb9dd229bbFabrice Di Meglio            try {
23250332925aa9db8c4826327edd85030a4791b7a8e6Michael Chan                if (cursor.moveToNext()) {
23260332925aa9db8c4826327edd85030a4791b7a8e6Michael Chan                    oldTimezoneDbVersion = cursor.getString(0);
23270332925aa9db8c4826327edd85030a4791b7a8e6Michael Chan                    cursor.close();
23280332925aa9db8c4826327edd85030a4791b7a8e6Michael Chan                    cursor = null;
23290332925aa9db8c4826327edd85030a4791b7a8e6Michael Chan                    // Also clean the CalendarCache table
23300332925aa9db8c4826327edd85030a4791b7a8e6Michael Chan                    db.execSQL("DELETE FROM CalendarCache;");
23310332925aa9db8c4826327edd85030a4791b7a8e6Michael Chan                }
233258313767dd0e7e3823c35ca61b40eddb9dd229bbFabrice Di Meglio            } finally {
23330332925aa9db8c4826327edd85030a4791b7a8e6Michael Chan                if (cursor != null) {
23340332925aa9db8c4826327edd85030a4791b7a8e6Michael Chan                    cursor.close();
23350332925aa9db8c4826327edd85030a4791b7a8e6Michael Chan                }
233658313767dd0e7e3823c35ca61b40eddb9dd229bbFabrice Di Meglio            }
2337315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        }
23382cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        initCalendarCacheTable203(db, oldTimezoneDbVersion);
2339315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio
2340315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        // Same as Gingerbread version 101
2341315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        updateCalendarCacheTableTo203(db);
2342315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio    }
2343315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio
2344c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan    private void upgradeToVersion202(SQLiteDatabase db) {
23457e7329964ddd60c98e93a7eda18b68944a630382Fabrice Di Meglio        // We will drop the "hidden" column from the calendar schema and add the "sync5" column
23462cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("ALTER TABLE Calendars RENAME TO Calendars_Backup;");
23477e7329964ddd60c98e93a7eda18b68944a630382Fabrice Di Meglio
23487e7329964ddd60c98e93a7eda18b68944a630382Fabrice Di Meglio        db.execSQL("DROP TRIGGER IF EXISTS calendar_cleanup");
2349180076a810558478f55ade53ebef0a2ddfa6bbc0Andy McFadden        createCalendarsTable202(db);
23507e7329964ddd60c98e93a7eda18b68944a630382Fabrice Di Meglio
23517e7329964ddd60c98e93a7eda18b68944a630382Fabrice Di Meglio        // Populate the new Calendars table and put into the "sync5" column the value of the
23527e7329964ddd60c98e93a7eda18b68944a630382Fabrice Di Meglio        // old "hidden" column
23532cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("INSERT INTO Calendars (" +
23542cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_id, " +
23552cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_account, " +
23562cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_account_type, " +
23572cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_id, " +
23582cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_version, " +
23592cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_time, " +
23602cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_local_id, " +
23612cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_dirty, " +
23622cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_mark, " +
23632cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "name, " +
23642cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "displayName, " +
23652cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "color, " +
23662cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "access_level, " +
23672cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "selected, " +
23682cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "sync_events, " +
23692cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "location, " +
23702cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "timezone, " +
23712cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "ownerAccount, " +
23722cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "organizerCanRespond, " +
23732cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "deleted, " +
23742cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "sync1, " +
23752cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "sync2, " +
23762cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "sync3, " +
23772cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "sync4," +
23782cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "sync5) " +
23797e7329964ddd60c98e93a7eda18b68944a630382Fabrice Di Meglio                "SELECT " +
23802cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_id, " +
23812cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_account, " +
23822cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_account_type, " +
23832cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_id, " +
23842cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_version, " +
23852cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_time, " +
23862cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_local_id, " +
23872cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_dirty, " +
23882cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_mark, " +
23892cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "name, " +
23902cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "displayName, " +
23912cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "color, " +
23922cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "access_level, " +
23932cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "selected, " +
23942cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "sync_events, " +
23952cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "location, " +
23962cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "timezone, " +
23972cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "ownerAccount, " +
23982cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "organizerCanRespond, " +
23992cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "deleted, " +
24002cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "sync1, " +
24012cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "sync2, " +
24022cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "sync3, " +
24032cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "sync4, " +
24042cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "hidden " +
24052cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "FROM Calendars_Backup;"
24067e7329964ddd60c98e93a7eda18b68944a630382Fabrice Di Meglio        );
24077e7329964ddd60c98e93a7eda18b68944a630382Fabrice Di Meglio
24087e7329964ddd60c98e93a7eda18b68944a630382Fabrice Di Meglio        // Drop the backup table
24092cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("DROP TABLE Calendars_Backup;");
24107e7329964ddd60c98e93a7eda18b68944a630382Fabrice Di Meglio    }
24117e7329964ddd60c98e93a7eda18b68944a630382Fabrice Di Meglio
2412c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan    private void upgradeToVersion201(SQLiteDatabase db) {
24132cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("ALTER TABLE Calendars ADD COLUMN sync4 TEXT;");
2414836bc8e9da32b8231f1b0d57be271730d7a5368dFabrice Di Meglio    }
2415836bc8e9da32b8231f1b0d57be271730d7a5368dFabrice Di Meglio
2416c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan    private void upgradeToVersion200(SQLiteDatabase db) {
24171b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio        // we cannot use here a Calendar.Calendars,URL constant for "url" as we are trying to make
24181b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio        // it disappear so we are keeping the hardcoded name "url" in all the SQLs
24192cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("ALTER TABLE Calendars RENAME TO Calendars_Backup;");
24201b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio
24211fc162fc3a3bb466a39146cf59a8b51ec5d9de52Fabrice Di Meglio        db.execSQL("DROP TRIGGER IF EXISTS calendar_cleanup");
24222cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        createCalendarsTable200(db);
24231b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio
24241b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio        // Populate the new Calendars table except the SYNC2 / SYNC3 columns
24252cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("INSERT INTO Calendars (" +
24262cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_id, " +
24272cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_account, " +
24282cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_account_type, " +
24292cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_id, " +
24302cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_version, " +
24312cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_time, " +
24322cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_local_id, " +
24332cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_dirty, " +
24342cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_mark, " +
24352cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "name, " +
24362cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "displayName, " +
24372cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "color, " +
24382cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "access_level, " +
24392cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "selected, " +
24402cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "sync_events, " +
24412cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "location, " +
24422cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "timezone, " +
24432cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "ownerAccount, " +
24442cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "organizerCanRespond, " +
24452cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "deleted, " +
24462cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "sync1) " +
24471b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio                "SELECT " +
24482cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_id, " +
24492cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_account, " +
24502cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_account_type, " +
24512cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_id, " +
24522cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_version, " +
24532cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_time, " +
24542cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_local_id, " +
24552cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_dirty, " +
24562cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_mark, " +
24572cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "name, " +
24582cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "displayName, " +
24592cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "color, " +
24602cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "access_level, " +
24612cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "selected, " +
24622cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "sync_events, " +
24632cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "location, " +
24642cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "timezone, " +
24652cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "ownerAccount, " +
24662cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "organizerCanRespond, " +
24672cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "0, " +
24682cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "url " +
24692cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "FROM Calendars_Backup;"
24701b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio        );
24711b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio
24721b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio        // Populate SYNC2 and SYNC3 columns - SYNC1 represent the old "url" column
24731b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio        // We will need to iterate over all the "com.google" type of calendars
24742cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        String selectSql = "SELECT _id, url" +
24752cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                " FROM Calendars_Backup" +
24762cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                " WHERE _sync_account_type='com.google'" +
24771b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio                " AND url IS NOT NULL;";
24781b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio
24792cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        String updateSql = "UPDATE Calendars SET " +
24802cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "sync2=?, " + // edit Url
24812cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "sync3=? " + // self Url
24822cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "WHERE _id=?;";
24831b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio
24841b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio        Cursor cursor = db.rawQuery(selectSql, null /* selection args */);
24850332925aa9db8c4826327edd85030a4791b7a8e6Michael Chan        if (cursor != null) {
24861b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio            try {
24870332925aa9db8c4826327edd85030a4791b7a8e6Michael Chan                if (cursor.getCount() > 0) {
24880332925aa9db8c4826327edd85030a4791b7a8e6Michael Chan                    Object[] bindArgs = new Object[3];
24890332925aa9db8c4826327edd85030a4791b7a8e6Michael Chan                    while (cursor.moveToNext()) {
24900332925aa9db8c4826327edd85030a4791b7a8e6Michael Chan                        Long id = cursor.getLong(0);
24910332925aa9db8c4826327edd85030a4791b7a8e6Michael Chan                        String url = cursor.getString(1);
24920332925aa9db8c4826327edd85030a4791b7a8e6Michael Chan                        String selfUrl = getSelfUrlFromEventsUrl(url);
24930332925aa9db8c4826327edd85030a4791b7a8e6Michael Chan                        String editUrl = getEditUrlFromEventsUrl(url);
24940332925aa9db8c4826327edd85030a4791b7a8e6Michael Chan
24950332925aa9db8c4826327edd85030a4791b7a8e6Michael Chan                        bindArgs[0] = editUrl;
24960332925aa9db8c4826327edd85030a4791b7a8e6Michael Chan                        bindArgs[1] = selfUrl;
24970332925aa9db8c4826327edd85030a4791b7a8e6Michael Chan                        bindArgs[2] = id;
24980332925aa9db8c4826327edd85030a4791b7a8e6Michael Chan
24990332925aa9db8c4826327edd85030a4791b7a8e6Michael Chan                        db.execSQL(updateSql, bindArgs);
25000332925aa9db8c4826327edd85030a4791b7a8e6Michael Chan                    }
25011b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio                }
25021b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio            } finally {
25031b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio                cursor.close();
25041b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio            }
25051b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio        }
25061b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio
25071b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio        // Drop the backup table
25082cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("DROP TABLE Calendars_Backup;");
250943b3eba05ef67bdd4b0a2b285b6ed2b377c136c5Fabrice Di Meglio    }
251043b3eba05ef67bdd4b0a2b285b6ed2b377c136c5Fabrice Di Meglio
251143b3eba05ef67bdd4b0a2b285b6ed2b377c136c5Fabrice Di Meglio    @VisibleForTesting
2512c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan    public static void upgradeToVersion69(SQLiteDatabase db) {
25137b40dde3168f4af2c757cb43955aa3bfe1668666Erik        // Clean up allDay events which could be in an invalid state from an earlier version
25147b40dde3168f4af2c757cb43955aa3bfe1668666Erik        // Some allDay events had hour, min, sec not set to zero, which throws elsewhere. This
2515e3730b9dce00439666e7ef324a28263a0ee92032Erik        // will go through the allDay events and make sure they have proper values and are in the
2516e3730b9dce00439666e7ef324a28263a0ee92032Erik        // correct timezone. Verifies that dtstart and dtend are in UTC and at midnight, that
2517e3730b9dce00439666e7ef324a28263a0ee92032Erik        // eventTimezone is set to UTC, tries to make sure duration is in days, and that dtstart2
2518e3730b9dce00439666e7ef324a28263a0ee92032Erik        // and dtend2 are at midnight in their timezone.
25192cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        final String sql = "SELECT _id, " +
25202cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "dtstart, " +
25212cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "dtend, " +
25222cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "duration, " +
25232cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "dtstart2, " +
25242cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "dtend2, " +
25252cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "eventTimezone, " +
25262cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "eventTimezone2, " +
25272cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "rrule " +
25282cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "FROM Events " +
25292cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "WHERE allDay=?";
25307cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio        Cursor cursor = db.rawQuery(sql, new String[] {"1"});
25317b40dde3168f4af2c757cb43955aa3bfe1668666Erik        if (cursor != null) {
25327b40dde3168f4af2c757cb43955aa3bfe1668666Erik            try {
25337b40dde3168f4af2c757cb43955aa3bfe1668666Erik                String timezone;
25347b40dde3168f4af2c757cb43955aa3bfe1668666Erik                String timezone2;
25357b40dde3168f4af2c757cb43955aa3bfe1668666Erik                String duration;
25367b40dde3168f4af2c757cb43955aa3bfe1668666Erik                Long dtstart;
25377b40dde3168f4af2c757cb43955aa3bfe1668666Erik                Long dtstart2;
25387b40dde3168f4af2c757cb43955aa3bfe1668666Erik                Long dtend;
25397b40dde3168f4af2c757cb43955aa3bfe1668666Erik                Long dtend2;
25407b40dde3168f4af2c757cb43955aa3bfe1668666Erik                Time time = new Time();
25417b40dde3168f4af2c757cb43955aa3bfe1668666Erik                Long id;
2542e3730b9dce00439666e7ef324a28263a0ee92032Erik                // some things need to be in utc so we call this frequently, cache to make faster
2543e3730b9dce00439666e7ef324a28263a0ee92032Erik                final String utc = Time.TIMEZONE_UTC;
25447b40dde3168f4af2c757cb43955aa3bfe1668666Erik                while (cursor.moveToNext()) {
25457b40dde3168f4af2c757cb43955aa3bfe1668666Erik                    String rrule = cursor.getString(8);
25467b40dde3168f4af2c757cb43955aa3bfe1668666Erik                    id = cursor.getLong(0);
25477b40dde3168f4af2c757cb43955aa3bfe1668666Erik                    dtstart = cursor.getLong(1);
25487b40dde3168f4af2c757cb43955aa3bfe1668666Erik                    dtstart2 = null;
25497b40dde3168f4af2c757cb43955aa3bfe1668666Erik                    timezone = cursor.getString(6);
25507b40dde3168f4af2c757cb43955aa3bfe1668666Erik                    timezone2 = cursor.getString(7);
25517b40dde3168f4af2c757cb43955aa3bfe1668666Erik                    duration = cursor.getString(3);
25527b40dde3168f4af2c757cb43955aa3bfe1668666Erik
2553e3730b9dce00439666e7ef324a28263a0ee92032Erik                    if (TextUtils.isEmpty(rrule)) {
25547b40dde3168f4af2c757cb43955aa3bfe1668666Erik                        // For non-recurring events dtstart and dtend should both have values
25557b40dde3168f4af2c757cb43955aa3bfe1668666Erik                        // and duration should be null.
25567b40dde3168f4af2c757cb43955aa3bfe1668666Erik                        dtend = cursor.getLong(2);
25577b40dde3168f4af2c757cb43955aa3bfe1668666Erik                        dtend2 = null;
25587b40dde3168f4af2c757cb43955aa3bfe1668666Erik                        // Since we made all three of these at the same time if timezone2 exists
25597b40dde3168f4af2c757cb43955aa3bfe1668666Erik                        // so should dtstart2 and dtend2.
25607b40dde3168f4af2c757cb43955aa3bfe1668666Erik                        if(!TextUtils.isEmpty(timezone2)) {
25617b40dde3168f4af2c757cb43955aa3bfe1668666Erik                            dtstart2 = cursor.getLong(4);
25627b40dde3168f4af2c757cb43955aa3bfe1668666Erik                            dtend2 = cursor.getLong(5);
25637b40dde3168f4af2c757cb43955aa3bfe1668666Erik                        }
25647b40dde3168f4af2c757cb43955aa3bfe1668666Erik
25657b40dde3168f4af2c757cb43955aa3bfe1668666Erik                        boolean update = false;
2566e3730b9dce00439666e7ef324a28263a0ee92032Erik                        if (!TextUtils.equals(timezone, utc)) {
2567e3730b9dce00439666e7ef324a28263a0ee92032Erik                            update = true;
2568e3730b9dce00439666e7ef324a28263a0ee92032Erik                            timezone = utc;
2569e3730b9dce00439666e7ef324a28263a0ee92032Erik                        }
2570e3730b9dce00439666e7ef324a28263a0ee92032Erik
2571e3730b9dce00439666e7ef324a28263a0ee92032Erik                        time.clear(timezone);
2572e3730b9dce00439666e7ef324a28263a0ee92032Erik                        update |= fixAllDayTime(time, timezone, dtstart);
25737b40dde3168f4af2c757cb43955aa3bfe1668666Erik                        dtstart = time.normalize(false);
2574e3730b9dce00439666e7ef324a28263a0ee92032Erik
2575e3730b9dce00439666e7ef324a28263a0ee92032Erik                        time.clear(timezone);
25767b40dde3168f4af2c757cb43955aa3bfe1668666Erik                        update |= fixAllDayTime(time, timezone, dtend);
25777b40dde3168f4af2c757cb43955aa3bfe1668666Erik                        dtend = time.normalize(false);
25787b40dde3168f4af2c757cb43955aa3bfe1668666Erik
25797b40dde3168f4af2c757cb43955aa3bfe1668666Erik                        if (dtstart2 != null) {
2580e3730b9dce00439666e7ef324a28263a0ee92032Erik                            time.clear(timezone2);
25817b40dde3168f4af2c757cb43955aa3bfe1668666Erik                            update |= fixAllDayTime(time, timezone2, dtstart2);
25827b40dde3168f4af2c757cb43955aa3bfe1668666Erik                            dtstart2 = time.normalize(false);
25837b40dde3168f4af2c757cb43955aa3bfe1668666Erik                        }
25847b40dde3168f4af2c757cb43955aa3bfe1668666Erik
25857b40dde3168f4af2c757cb43955aa3bfe1668666Erik                        if (dtend2 != null) {
2586e3730b9dce00439666e7ef324a28263a0ee92032Erik                            time.clear(timezone2);
25877b40dde3168f4af2c757cb43955aa3bfe1668666Erik                            update |= fixAllDayTime(time, timezone2, dtend2);
25887b40dde3168f4af2c757cb43955aa3bfe1668666Erik                            dtend2 = time.normalize(false);
25897b40dde3168f4af2c757cb43955aa3bfe1668666Erik                        }
25907b40dde3168f4af2c757cb43955aa3bfe1668666Erik
25917b40dde3168f4af2c757cb43955aa3bfe1668666Erik                        if (!TextUtils.isEmpty(duration)) {
25927b40dde3168f4af2c757cb43955aa3bfe1668666Erik                            update = true;
25937b40dde3168f4af2c757cb43955aa3bfe1668666Erik                        }
25947b40dde3168f4af2c757cb43955aa3bfe1668666Erik
25957b40dde3168f4af2c757cb43955aa3bfe1668666Erik                        if (update) {
25967b40dde3168f4af2c757cb43955aa3bfe1668666Erik                            // enforce duration being null
25972cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                            db.execSQL("UPDATE Events SET " +
25982cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                                    "dtstart=?, " +
25992cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                                    "dtend=?, " +
26002cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                                    "dtstart2=?, " +
26012cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                                    "dtend2=?, " +
26022cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                                    "duration=?, " +
26032cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                                    "eventTimezone=?, " +
26042cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                                    "eventTimezone2=? " +
26052cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                                    "WHERE _id=?",
26067cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                                    new Object[] {
26077cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                                            dtstart,
26087cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                                            dtend,
26097cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                                            dtstart2,
26107cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                                            dtend2,
26117cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                                            null,
26127cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                                            timezone,
26137cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                                            timezone2,
26147cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                                            id}
26157cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                            );
26167b40dde3168f4af2c757cb43955aa3bfe1668666Erik                        }
26177b40dde3168f4af2c757cb43955aa3bfe1668666Erik
26187b40dde3168f4af2c757cb43955aa3bfe1668666Erik                    } else {
26197b40dde3168f4af2c757cb43955aa3bfe1668666Erik                        // For recurring events only dtstart and duration should be used.
26207b40dde3168f4af2c757cb43955aa3bfe1668666Erik                        // We ignore dtend since it will be overwritten if the event changes to a
26217b40dde3168f4af2c757cb43955aa3bfe1668666Erik                        // non-recurring event and won't be used otherwise.
26227b40dde3168f4af2c757cb43955aa3bfe1668666Erik                        if(!TextUtils.isEmpty(timezone2)) {
26237b40dde3168f4af2c757cb43955aa3bfe1668666Erik                            dtstart2 = cursor.getLong(4);
26247b40dde3168f4af2c757cb43955aa3bfe1668666Erik                        }
26257b40dde3168f4af2c757cb43955aa3bfe1668666Erik
26267b40dde3168f4af2c757cb43955aa3bfe1668666Erik                        boolean update = false;
2627e3730b9dce00439666e7ef324a28263a0ee92032Erik                        if (!TextUtils.equals(timezone, utc)) {
2628e3730b9dce00439666e7ef324a28263a0ee92032Erik                            update = true;
2629e3730b9dce00439666e7ef324a28263a0ee92032Erik                            timezone = utc;
2630e3730b9dce00439666e7ef324a28263a0ee92032Erik                        }
2631e3730b9dce00439666e7ef324a28263a0ee92032Erik
2632e3730b9dce00439666e7ef324a28263a0ee92032Erik                        time.clear(timezone);
2633e3730b9dce00439666e7ef324a28263a0ee92032Erik                        update |= fixAllDayTime(time, timezone, dtstart);
26347b40dde3168f4af2c757cb43955aa3bfe1668666Erik                        dtstart = time.normalize(false);
26357b40dde3168f4af2c757cb43955aa3bfe1668666Erik
26367b40dde3168f4af2c757cb43955aa3bfe1668666Erik                        if (dtstart2 != null) {
2637e3730b9dce00439666e7ef324a28263a0ee92032Erik                            time.clear(timezone2);
26387b40dde3168f4af2c757cb43955aa3bfe1668666Erik                            update |= fixAllDayTime(time, timezone2, dtstart2);
26397b40dde3168f4af2c757cb43955aa3bfe1668666Erik                            dtstart2 = time.normalize(false);
26407b40dde3168f4af2c757cb43955aa3bfe1668666Erik                        }
26417b40dde3168f4af2c757cb43955aa3bfe1668666Erik
26427b40dde3168f4af2c757cb43955aa3bfe1668666Erik                        if (TextUtils.isEmpty(duration)) {
26437b40dde3168f4af2c757cb43955aa3bfe1668666Erik                            // If duration was missing assume a 1 day duration
26447b40dde3168f4af2c757cb43955aa3bfe1668666Erik                            duration = "P1D";
26457b40dde3168f4af2c757cb43955aa3bfe1668666Erik                            update = true;
26467b40dde3168f4af2c757cb43955aa3bfe1668666Erik                        } else {
26477b40dde3168f4af2c757cb43955aa3bfe1668666Erik                            int len = duration.length();
26487b40dde3168f4af2c757cb43955aa3bfe1668666Erik                            // TODO fix durations in other formats as well
26497b40dde3168f4af2c757cb43955aa3bfe1668666Erik                            if (duration.charAt(0) == 'P' &&
26507b40dde3168f4af2c757cb43955aa3bfe1668666Erik                                    duration.charAt(len - 1) == 'S') {
26517b40dde3168f4af2c757cb43955aa3bfe1668666Erik                                int seconds = Integer.parseInt(duration.substring(1, len - 1));
26527b40dde3168f4af2c757cb43955aa3bfe1668666Erik                                int days = (seconds + DAY_IN_SECONDS - 1) / DAY_IN_SECONDS;
26537b40dde3168f4af2c757cb43955aa3bfe1668666Erik                                duration = "P" + days + "D";
26547b40dde3168f4af2c757cb43955aa3bfe1668666Erik                                update = true;
26557b40dde3168f4af2c757cb43955aa3bfe1668666Erik                            }
26567b40dde3168f4af2c757cb43955aa3bfe1668666Erik                        }
26577b40dde3168f4af2c757cb43955aa3bfe1668666Erik
26587b40dde3168f4af2c757cb43955aa3bfe1668666Erik                        if (update) {
26597b40dde3168f4af2c757cb43955aa3bfe1668666Erik                            // If there were other problems also enforce dtend being null
26602cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                            db.execSQL("UPDATE Events SET " +
26612cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                                    "dtstart=?, " +
26622cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                                    "dtend=?, " +
26632cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                                    "dtstart2=?, " +
26642cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                                    "dtend2=?, " +
26652cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                                    "duration=?," +
26662cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                                    "eventTimezone=?, " +
26672cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                                    "eventTimezone2=? " +
26682cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                                    "WHERE _id=?",
26697cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                                    new Object[] {
26707cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                                            dtstart,
26717cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                                            null,
26727cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                                            dtstart2,
26737cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                                            null,
26747cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                                            duration,
26757cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                                            timezone,
26767cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                                            timezone2,
26777cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                                            id}
26787cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                            );
26797b40dde3168f4af2c757cb43955aa3bfe1668666Erik                        }
26807b40dde3168f4af2c757cb43955aa3bfe1668666Erik                    }
26817b40dde3168f4af2c757cb43955aa3bfe1668666Erik                }
26827b40dde3168f4af2c757cb43955aa3bfe1668666Erik            } finally {
26837b40dde3168f4af2c757cb43955aa3bfe1668666Erik                cursor.close();
26847b40dde3168f4af2c757cb43955aa3bfe1668666Erik            }
26857b40dde3168f4af2c757cb43955aa3bfe1668666Erik        }
26867b40dde3168f4af2c757cb43955aa3bfe1668666Erik    }
26877b40dde3168f4af2c757cb43955aa3bfe1668666Erik
2688bf897b03effb752368a98cfb89e6b90cfdde50fcMarc Blank    private void upgradeToVersion66(SQLiteDatabase db) {
2689bf897b03effb752368a98cfb89e6b90cfdde50fcMarc Blank        // Add a column to indicate whether the event organizer can respond to his own events
2690bf897b03effb752368a98cfb89e6b90cfdde50fcMarc Blank        // The UI should not show attendee status for events in calendars with this column = 0
26912cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("ALTER TABLE Calendars" +
26922cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                " ADD COLUMN organizerCanRespond INTEGER NOT NULL DEFAULT 1;");
2693cf9dc6b9bd031b1f6f811a32326ee85429c94debMarc Blank    }
2694cf9dc6b9bd031b1f6f811a32326ee85429c94debMarc Blank
2695162c7c9bbd53b623fbe913b376e7f7f42915bb59Marc Blank    private void upgradeToVersion64(SQLiteDatabase db) {
2696162c7c9bbd53b623fbe913b376e7f7f42915bb59Marc Blank        // Add a column that may be used by sync adapters
26972cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("ALTER TABLE Events" +
26982cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                " ADD COLUMN syncAdapterData TEXT;");
26992d1b3d70a6ebce8194932f8a8355d97a89da113fFabrice Di Meglio    }
27002d1b3d70a6ebce8194932f8a8355d97a89da113fFabrice Di Meglio
2701ae4f20e120d3107cef20be860a612c9c23816295Erik    private void upgradeToVersion62(SQLiteDatabase db) {
2702ae4f20e120d3107cef20be860a612c9c23816295Erik        // New columns are to transition to having allDay events in the local timezone
27032cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("ALTER TABLE Events" +
27042cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                " ADD COLUMN dtstart2 INTEGER;");
27052cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("ALTER TABLE Events" +
27062cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                " ADD COLUMN dtend2 INTEGER;");
27072cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("ALTER TABLE Events" +
27082cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                " ADD COLUMN eventTimezone2 TEXT;");
2709ae4f20e120d3107cef20be860a612c9c23816295Erik
2710ae4f20e120d3107cef20be860a612c9c23816295Erik        String[] allDayBit = new String[] {"0"};
2711ae4f20e120d3107cef20be860a612c9c23816295Erik        // Copy over all the data that isn't an all day event.
27122cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("UPDATE Events SET " +
27132cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "dtstart2=dtstart," +
27142cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "dtend2=dtend," +
27152cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "eventTimezone2=eventTimezone " +
27162cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "WHERE allDay=?;",
2717ae4f20e120d3107cef20be860a612c9c23816295Erik                allDayBit /* selection args */);
2718ae4f20e120d3107cef20be860a612c9c23816295Erik
2719ae4f20e120d3107cef20be860a612c9c23816295Erik        // "cursor" iterates over all the calendars
2720ae4f20e120d3107cef20be860a612c9c23816295Erik        allDayBit[0] = "1";
27212cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        Cursor cursor = db.rawQuery("SELECT Events._id," +
27222cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "dtstart," +
27232cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "dtend," +
27242cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "eventTimezone," +
27252cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "timezone " +
27262cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "FROM Events INNER JOIN Calendars " +
27272cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "WHERE Events.calendar_id=Calendars._id" +
27282cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                " AND allDay=?",
2729ae4f20e120d3107cef20be860a612c9c23816295Erik                allDayBit /* selection args */);
2730ae4f20e120d3107cef20be860a612c9c23816295Erik
2731ae4f20e120d3107cef20be860a612c9c23816295Erik        Time oldTime = new Time();
2732ae4f20e120d3107cef20be860a612c9c23816295Erik        Time newTime = new Time();
2733ae4f20e120d3107cef20be860a612c9c23816295Erik        // Update the allday events in the new columns
2734ae4f20e120d3107cef20be860a612c9c23816295Erik        if (cursor != null) {
2735ae4f20e120d3107cef20be860a612c9c23816295Erik            try {
2736ae4f20e120d3107cef20be860a612c9c23816295Erik                String[] newData = new String[4];
2737ae4f20e120d3107cef20be860a612c9c23816295Erik                cursor.moveToPosition(-1);
2738ae4f20e120d3107cef20be860a612c9c23816295Erik                while (cursor.moveToNext()) {
2739ae4f20e120d3107cef20be860a612c9c23816295Erik                    long id = cursor.getLong(0); // Order from query above
2740ae4f20e120d3107cef20be860a612c9c23816295Erik                    long dtstart = cursor.getLong(1);
2741ae4f20e120d3107cef20be860a612c9c23816295Erik                    long dtend = cursor.getLong(2);
2742ae4f20e120d3107cef20be860a612c9c23816295Erik                    String eTz = cursor.getString(3); // current event timezone
2743ae4f20e120d3107cef20be860a612c9c23816295Erik                    String tz = cursor.getString(4); // Calendar timezone
2744dbaad88527665d5144a8a178fa822f58d2bc7d05Erik                    //If there's no timezone for some reason use UTC by default.
2745dbaad88527665d5144a8a178fa822f58d2bc7d05Erik                    if(eTz == null) {
2746dbaad88527665d5144a8a178fa822f58d2bc7d05Erik                        eTz = Time.TIMEZONE_UTC;
2747dbaad88527665d5144a8a178fa822f58d2bc7d05Erik                    }
2748ae4f20e120d3107cef20be860a612c9c23816295Erik
2749ae4f20e120d3107cef20be860a612c9c23816295Erik                    // Convert start time for all day events into the timezone of their calendar
2750ae4f20e120d3107cef20be860a612c9c23816295Erik                    oldTime.clear(eTz);
2751ae4f20e120d3107cef20be860a612c9c23816295Erik                    oldTime.set(dtstart);
2752ae4f20e120d3107cef20be860a612c9c23816295Erik                    newTime.clear(tz);
2753ae4f20e120d3107cef20be860a612c9c23816295Erik                    newTime.set(oldTime.monthDay, oldTime.month, oldTime.year);
2754ae4f20e120d3107cef20be860a612c9c23816295Erik                    newTime.normalize(false);
2755ae4f20e120d3107cef20be860a612c9c23816295Erik                    dtstart = newTime.toMillis(false /*ignoreDst*/);
2756ae4f20e120d3107cef20be860a612c9c23816295Erik
2757ae4f20e120d3107cef20be860a612c9c23816295Erik                    // Convert end time for all day events into the timezone of their calendar
2758ae4f20e120d3107cef20be860a612c9c23816295Erik                    oldTime.clear(eTz);
2759ae4f20e120d3107cef20be860a612c9c23816295Erik                    oldTime.set(dtend);
2760ae4f20e120d3107cef20be860a612c9c23816295Erik                    newTime.clear(tz);
2761ae4f20e120d3107cef20be860a612c9c23816295Erik                    newTime.set(oldTime.monthDay, oldTime.month, oldTime.year);
2762ae4f20e120d3107cef20be860a612c9c23816295Erik                    newTime.normalize(false);
2763ae4f20e120d3107cef20be860a612c9c23816295Erik                    dtend = newTime.toMillis(false /*ignoreDst*/);
2764ae4f20e120d3107cef20be860a612c9c23816295Erik
2765ae4f20e120d3107cef20be860a612c9c23816295Erik                    newData[0] = String.valueOf(dtstart);
2766ae4f20e120d3107cef20be860a612c9c23816295Erik                    newData[1] = String.valueOf(dtend);
2767ae4f20e120d3107cef20be860a612c9c23816295Erik                    newData[2] = tz;
2768ae4f20e120d3107cef20be860a612c9c23816295Erik                    newData[3] = String.valueOf(id);
27692cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                    db.execSQL("UPDATE Events SET " +
27702cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                            "dtstart2=?, " +
27712cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                            "dtend2=?, " +
27722cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                            "eventTimezone2=? " +
27732cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                            "WHERE _id=?",
2774ae4f20e120d3107cef20be860a612c9c23816295Erik                            newData);
2775ae4f20e120d3107cef20be860a612c9c23816295Erik                }
2776ae4f20e120d3107cef20be860a612c9c23816295Erik            } finally {
2777ae4f20e120d3107cef20be860a612c9c23816295Erik                cursor.close();
2778ae4f20e120d3107cef20be860a612c9c23816295Erik            }
2779ae4f20e120d3107cef20be860a612c9c23816295Erik        }
2780ae4f20e120d3107cef20be860a612c9c23816295Erik    }
2781ae4f20e120d3107cef20be860a612c9c23816295Erik
2782ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio    private void upgradeToVersion61(SQLiteDatabase db) {
2783315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        db.execSQL("DROP TABLE IF EXISTS CalendarCache;");
2784315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio
2785315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        // IF NOT EXISTS should be normal pattern for table creation
27862cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("CREATE TABLE IF NOT EXISTS CalendarCache (" +
27872cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_id INTEGER PRIMARY KEY," +
27882cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "key TEXT NOT NULL," +
27892cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "value TEXT" +
2790315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio                ");");
2791315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio
27922cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("INSERT INTO CalendarCache (" +
27932cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "key, " +
27942cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "value) VALUES (" +
27952cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "'timezoneDatabaseVersion',"  +
27962cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "'2009s'" +
2797315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio                ");");
2798ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio    }
2799ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio
2800ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff    private void upgradeToVersion60(SQLiteDatabase db) {
2801ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        // Switch to CalendarProvider2
2802d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff        upgradeSyncState(db);
2803ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        db.execSQL("DROP TRIGGER IF EXISTS calendar_cleanup");
28042cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("CREATE TRIGGER calendar_cleanup DELETE ON Calendars " +
2805ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff                "BEGIN " +
28062cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                ("DELETE FROM Events" +
28072cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                        " WHERE calendar_id=old._id;") +
2808ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff                "END");
28092cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("ALTER TABLE Events" +
28102cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                " ADD COLUMN deleted INTEGER NOT NULL DEFAULT 0;");
2811ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        db.execSQL("DROP TRIGGER IF EXISTS events_insert");
28127cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio        // Trigger to set event's sync_account
28132cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("CREATE TRIGGER events_insert AFTER INSERT ON Events " +
2814ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff                "BEGIN " +
28152cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "UPDATE Events" +
28162cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                " SET _sync_account=" +
28172cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                " (SELECT _sync_account FROM Calendars" +
28182cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                " WHERE Calendars._id=new.calendar_id)," +
28192cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_account_type=" +
28202cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                " (SELECT _sync_account_type FROM Calendars" +
28212cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                " WHERE Calendars._id=new.calendar_id) " +
28222cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "WHERE Events._id=new._id;" +
2823ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff                "END");
2824ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        db.execSQL("DROP TABLE IF EXISTS DeletedEvents;");
2825ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        db.execSQL("DROP TRIGGER IF EXISTS events_cleanup_delete");
28267cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio        // Trigger to remove data tied to an event when we delete that event.
28272cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("CREATE TRIGGER events_cleanup_delete DELETE ON Events " +
2828ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff                "BEGIN " +
28292cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                ("DELETE FROM Instances" +
28302cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                    " WHERE event_id=old._id;" +
28312cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "DELETE FROM EventsRawTimes" +
28322cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                    " WHERE event_id=old._id;" +
28332cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "DELETE FROM Attendees" +
28342cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                    " WHERE event_id=old._id;" +
28352cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "DELETE FROM Reminders" +
28362cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                    " WHERE event_id=old._id;" +
28372cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "DELETE FROM CalendarAlerts" +
28382cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                    " WHERE event_id=old._id;" +
28392cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "DELETE FROM ExtendedProperties" +
28402cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                    " WHERE event_id=old._id;") +
2841ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff                "END");
2842ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        db.execSQL("DROP TRIGGER IF EXISTS attendees_update");
2843ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        db.execSQL("DROP TRIGGER IF EXISTS attendees_insert");
2844ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        db.execSQL("DROP TRIGGER IF EXISTS attendees_delete");
2845ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        db.execSQL("DROP TRIGGER IF EXISTS reminders_update");
2846ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        db.execSQL("DROP TRIGGER IF EXISTS reminders_insert");
2847ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        db.execSQL("DROP TRIGGER IF EXISTS reminders_delete");
2848ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        db.execSQL("DROP TRIGGER IF EXISTS extended_properties_update");
2849ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        db.execSQL("DROP TRIGGER IF EXISTS extended_properties_insert");
2850ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        db.execSQL("DROP TRIGGER IF EXISTS extended_properties_delete");
2851ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff    }
2852ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff
2853ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff    private void upgradeToVersion59(SQLiteDatabase db) {
2854ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        db.execSQL("DROP TABLE IF EXISTS BusyBits;");
28552cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("CREATE TEMPORARY TABLE CalendarMetaData_Backup(" +
28562cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_id," +
28572cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "localTimezone," +
28582cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "minInstance," +
28592cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "maxInstance" +
28607cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                ");");
28612cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("INSERT INTO CalendarMetaData_Backup " +
28627cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                "SELECT " +
28632cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_id," +
28642cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "localTimezone," +
28652cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "minInstance," +
28662cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "maxInstance" +
28672cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                " FROM CalendarMetaData;");
28682cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("DROP TABLE CalendarMetaData;");
28692cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        createCalendarMetaDataTable59(db);
28702cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("INSERT INTO CalendarMetaData " +
28717cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                "SELECT " +
28722cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_id," +
28732cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "localTimezone," +
28742cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "minInstance," +
28752cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "maxInstance" +
28762cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                " FROM CalendarMetaData_Backup;");
28772cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("DROP TABLE CalendarMetaData_Backup;");
2878ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff    }
2879ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff
2880ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff    private void upgradeToVersion57(SQLiteDatabase db) {
28812cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("ALTER TABLE Events" +
28822cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                " ADD COLUMN guestsCanModify" +
28837cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                " INTEGER NOT NULL DEFAULT 0;");
28842cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("ALTER TABLE Events" +
28852cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                " ADD COLUMN guestsCanInviteOthers" +
28867cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                " INTEGER NOT NULL DEFAULT 1;");
28872cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("ALTER TABLE Events" +
28882cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                " ADD COLUMN guestsCanSeeGuests" +
28897cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                " INTEGER NOT NULL DEFAULT 1;");
28902cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("ALTER TABLE Events" +
28912cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                " ADD COLUMN organizer" +
28927cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                " STRING;");
28932cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("UPDATE Events SET organizer=" +
28942cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "(SELECT attendeeEmail" +
28952cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                " FROM Attendees"  +
28967cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                " WHERE " +
28972cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "Attendees.event_id=" +
28982cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "Events._id" +
28997cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                " AND " +
29002cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "Attendees.attendeeRelationship=2);");
2901ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff    }
2902ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff
29031599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio    private void upgradeToVersion56(SQLiteDatabase db) {
29042cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("ALTER TABLE Calendars" +
29052cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                " ADD COLUMN ownerAccount TEXT;");
29062cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("ALTER TABLE Events" +
2907d5f4742d7ba16d791edd9fd33a1a2a42eeac709bRoboErik                " ADD COLUMN hasAttendeeData INTEGER NOT NULL DEFAULT 0;");
29087cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio
29091599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio        // Clear _sync_dirty to avoid a client-to-server sync that could blow away
29101599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio        // server attendees.
29111599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio        // Clear _sync_version to pull down the server's event (with attendees)
29121599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio        // Change the URLs from full-selfattendance to full
29132cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("UPDATE Events"
29142cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                + " SET _sync_dirty=0, "
29152cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                + "_sync_version=NULL, "
29162cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                + "_sync_id="
29172cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                + "REPLACE(_sync_id, " +
29187cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                    "'/private/full-selfattendance', '/private/full'),"
29192cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                + "commentsUri="
29202cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                + "REPLACE(commentsUri, " +
29217cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                    "'/private/full-selfattendance', '/private/full');");
29227cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio
29232cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("UPDATE Calendars"
29242cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                + " SET url="
29252cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                + "REPLACE(url, '/private/full-selfattendance', '/private/full');");
29261599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio
29271599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio        // "cursor" iterates over all the calendars
29282cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        Cursor cursor = db.rawQuery("SELECT _id, " +
29292cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "url FROM Calendars",
29301599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio                null /* selection args */);
29311599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio        // Add the owner column.
29321599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio        if (cursor != null) {
29331599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio            try {
29342cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                final String updateSql = "UPDATE Calendars" +
29352cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                        " SET ownerAccount=?" +
29362cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                        " WHERE _id=?";
29371599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio                while (cursor.moveToNext()) {
29381599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio                    Long id = cursor.getLong(0);
29391599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio                    String url = cursor.getString(1);
29401599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio                    String owner = calendarEmailAddressFromFeedUrl(url);
29417cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                    db.execSQL(updateSql, new Object[] {owner, id});
29421599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio                }
29431599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio            } finally {
29441599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio                cursor.close();
29451599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio            }
29461599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio        }
29471599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio    }
29481599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio
29491599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio    private void upgradeResync(SQLiteDatabase db) {
29501599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio        // Delete sync state, so all records will be re-synced.
29512cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("DELETE FROM _sync_state;");
29521599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio
29531599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio        // "cursor" iterates over all the calendars
29542cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        Cursor cursor = db.rawQuery("SELECT _sync_account," +
29552cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_account_type,url FROM Calendars",
29561599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio                null /* selection args */);
29571599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio        if (cursor != null) {
29581599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio            try {
29591599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio                while (cursor.moveToNext()) {
29601599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio                    String accountName = cursor.getString(0);
29611599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio                    String accountType = cursor.getString(1);
29621599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio                    final Account account = new Account(accountName, accountType);
29631599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio                    String calendarUrl = cursor.getString(2);
29641599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio                    scheduleSync(account, false /* two-way sync */, calendarUrl);
29651599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio                }
29661599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio            } finally {
29671599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio                cursor.close();
29681599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio            }
29691599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio        }
29701599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio    }
29711599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio
2972ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff    private void upgradeToVersion55(SQLiteDatabase db) {
29732cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("ALTER TABLE Calendars ADD COLUMN " +
29742cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_account_type TEXT;");
29752cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("ALTER TABLE Events ADD COLUMN " +
29762cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_account_type TEXT;");
2977ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        db.execSQL("ALTER TABLE DeletedEvents ADD COLUMN _sync_account_type TEXT;");
29782cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("UPDATE Calendars"
29792cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                + " SET _sync_account_type='com.google'"
29802cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                + " WHERE _sync_account IS NOT NULL");
29812cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("UPDATE Events"
29822cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                + " SET _sync_account_type='com.google'"
29832cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                + " WHERE _sync_account IS NOT NULL");
2984ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        db.execSQL("UPDATE DeletedEvents"
2985ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff                + " SET _sync_account_type='com.google'"
2986ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff                + " WHERE _sync_account IS NOT NULL");
2987ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        Log.w(TAG, "re-creating eventSyncAccountAndIdIndex");
2988ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        db.execSQL("DROP INDEX eventSyncAccountAndIdIndex");
29892cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("CREATE INDEX eventSyncAccountAndIdIndex ON Events ("
29902cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                + "_sync_account_type, "
29912cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                + "_sync_account, "
29922cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                + "_sync_id);");
2993ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff    }
2994ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff
2995ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff    private void upgradeToVersion54(SQLiteDatabase db) {
2996ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        Log.w(TAG, "adding eventSyncAccountAndIdIndex");
2997ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        db.execSQL("CREATE INDEX eventSyncAccountAndIdIndex ON Events ("
29982cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                + "_sync_account, _sync_id);");
2999ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff    }
3000ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff
3001ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff    private void upgradeToVersion53(SQLiteDatabase db) {
3002ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        Log.w(TAG, "Upgrading CalendarAlerts table");
30032cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("ALTER TABLE CalendarAlerts ADD COLUMN " +
3004d5f4742d7ba16d791edd9fd33a1a2a42eeac709bRoboErik                "creationTime INTEGER NOT NULL DEFAULT 0;");
30052cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("ALTER TABLE CalendarAlerts ADD COLUMN " +
3006d5f4742d7ba16d791edd9fd33a1a2a42eeac709bRoboErik                "receivedTime INTEGER NOT NULL DEFAULT 0;");
30072cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("ALTER TABLE CalendarAlerts ADD COLUMN " +
3008d5f4742d7ba16d791edd9fd33a1a2a42eeac709bRoboErik                "notifyTime INTEGER NOT NULL DEFAULT 0;");
3009ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff    }
3010ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff
3011ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff    private void upgradeToVersion52(SQLiteDatabase db) {
3012ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        // We added "originalAllDay" to the Events table to keep track of
3013ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        // the allDay status of the original recurring event for entries
3014ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        // that are exceptions to that recurring event.  We need this so
3015ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        // that we can format the date correctly for the "originalInstanceTime"
3016ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        // column when we make a change to the recurrence exception and
3017ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        // send it to the server.
30182cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("ALTER TABLE Events ADD COLUMN " +
30192cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "originalAllDay INTEGER;");
3020ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff
3021ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        // Iterate through the Events table and for each recurrence
3022ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        // exception, fill in the correct value for "originalAllDay",
3023ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        // if possible.  The only times where this might not be possible
3024ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        // are (1) the original recurring event no longer exists, or
3025ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        // (2) the original recurring event does not yet have a _sync_id
3026ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        // because it was created on the phone and hasn't been synced to the
3027ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        // server yet.  In both cases the originalAllDay field will be set
3028ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        // to null.  In the first case we don't care because the recurrence
3029ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        // exception will not be displayed and we won't be able to make
3030ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        // any changes to it (and even if we did, the server should ignore
3031ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        // them, right?).  In the second case, the calendar client already
3032ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        // disallows making changes to an instance of a recurring event
3033ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        // until the recurring event has been synced to the server so the
3034ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        // second case should never occur.
3035ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff
3036ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        // "cursor" iterates over all the recurrences exceptions.
30372cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        Cursor cursor = db.rawQuery("SELECT _id," +
30382cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "originalEvent" +
30392cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                " FROM Events" +
30402cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                " WHERE originalEvent IS NOT NULL",
30417cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                null /* selection args */);
3042ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        if (cursor != null) {
3043ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff            try {
3044ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff                while (cursor.moveToNext()) {
3045ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff                    long id = cursor.getLong(0);
3046ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff                    String originalEvent = cursor.getString(1);
3047ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff
3048ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff                    // Find the original recurring event (if it exists)
30492cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                    Cursor recur = db.rawQuery("SELECT allDay" +
30502cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                            " FROM Events" +
30512cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                            " WHERE _sync_id=?",
30527cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                            new String[] {originalEvent});
3053ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff                    if (recur == null) {
3054ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff                        continue;
3055ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff                    }
3056ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff
3057ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff                    try {
3058ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff                        // Fill in the "originalAllDay" field of the
3059ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff                        // recurrence exception with the "allDay" value
3060ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff                        // from the recurring event.
3061ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff                        if (recur.moveToNext()) {
3062ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff                            int allDay = recur.getInt(0);
30632cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                            db.execSQL("UPDATE Events" +
30642cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                                    " SET originalAllDay=" + allDay +
30652cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                                    " WHERE _id="+id);
3066ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff                        }
3067ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff                    } finally {
3068ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff                        recur.close();
3069ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff                    }
3070ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff                }
3071ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff            } finally {
3072ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff                cursor.close();
3073ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff            }
30749f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
30759f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
30769f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
3077ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff    private void upgradeToVersion51(SQLiteDatabase db) {
3078ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        Log.w(TAG, "Upgrading DeletedEvents table");
3079ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff
3080ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        // We don't have enough information to fill in the correct
3081ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        // value of the calendar_id for old rows in the DeletedEvents
3082ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        // table, but rows in that table are transient so it is unlikely
3083ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        // that there are any rows.  Plus, the calendar_id is used only
3084ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        // when deleting a calendar, which is a rare event.  All new rows
3085ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        // will have the correct calendar_id.
3086ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        db.execSQL("ALTER TABLE DeletedEvents ADD COLUMN calendar_id INTEGER;");
3087ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff
3088ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        // Trigger to remove a calendar's events when we delete the calendar
3089ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        db.execSQL("DROP TRIGGER IF EXISTS calendar_cleanup");
30902cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("CREATE TRIGGER calendar_cleanup DELETE ON Calendars " +
3091ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff                "BEGIN " +
30922cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "DELETE FROM Events WHERE calendar_id=" +
30932cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                    "old._id;" +
3094ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff                "DELETE FROM DeletedEvents WHERE calendar_id = old._id;" +
3095ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff                "END");
3096ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        db.execSQL("DROP TRIGGER IF EXISTS event_to_deleted");
3097ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff    }
3098ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff
30999f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private void dropTables(SQLiteDatabase db) {
31000d8699eedb0f3bcec1854b9753ae59154a122726Michael Chan        Log.i(TAG, "Clearing database");
31010d8699eedb0f3bcec1854b9753ae59154a122726Michael Chan
31020d8699eedb0f3bcec1854b9753ae59154a122726Michael Chan        String[] columns = {
31030d8699eedb0f3bcec1854b9753ae59154a122726Michael Chan                "type", "name"
31040d8699eedb0f3bcec1854b9753ae59154a122726Michael Chan        };
31050d8699eedb0f3bcec1854b9753ae59154a122726Michael Chan        Cursor cursor = db.query("sqlite_master", columns, null, null, null, null, null);
31060d8699eedb0f3bcec1854b9753ae59154a122726Michael Chan        if (cursor == null) {
31070d8699eedb0f3bcec1854b9753ae59154a122726Michael Chan            return;
31080d8699eedb0f3bcec1854b9753ae59154a122726Michael Chan        }
31090d8699eedb0f3bcec1854b9753ae59154a122726Michael Chan        try {
31100d8699eedb0f3bcec1854b9753ae59154a122726Michael Chan            while (cursor.moveToNext()) {
31110d8699eedb0f3bcec1854b9753ae59154a122726Michael Chan                final String name = cursor.getString(1);
31120d8699eedb0f3bcec1854b9753ae59154a122726Michael Chan                if (!name.startsWith("sqlite_")) {
31130d8699eedb0f3bcec1854b9753ae59154a122726Michael Chan                    // If it's not a SQL-controlled entity, drop it
31140d8699eedb0f3bcec1854b9753ae59154a122726Michael Chan                    final String sql = "DROP " + cursor.getString(0) + " IF EXISTS " + name;
31150d8699eedb0f3bcec1854b9753ae59154a122726Michael Chan                    try {
31160d8699eedb0f3bcec1854b9753ae59154a122726Michael Chan                        db.execSQL(sql);
31170d8699eedb0f3bcec1854b9753ae59154a122726Michael Chan                    } catch (SQLException e) {
31180d8699eedb0f3bcec1854b9753ae59154a122726Michael Chan                        Log.e(TAG, "Error executing " + sql + " " + e.toString());
31190d8699eedb0f3bcec1854b9753ae59154a122726Michael Chan                    }
31200d8699eedb0f3bcec1854b9753ae59154a122726Michael Chan                }
31210d8699eedb0f3bcec1854b9753ae59154a122726Michael Chan            }
31220d8699eedb0f3bcec1854b9753ae59154a122726Michael Chan        } finally {
31230d8699eedb0f3bcec1854b9753ae59154a122726Michael Chan            cursor.close();
31240d8699eedb0f3bcec1854b9753ae59154a122726Michael Chan        }
31259f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
31269f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
31279f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    @Override
31289f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    public synchronized SQLiteDatabase getWritableDatabase() {
31299f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        SQLiteDatabase db = super.getWritableDatabase();
31309f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        return db;
31319f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
31329f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
31339f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    public SyncStateContentProviderHelper getSyncState() {
31349f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        return mSyncState;
31359f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
31369f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
31379f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    /**
31389f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * Schedule a calendar sync for the account.
31399f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * @param account the account for which to schedule a sync
31409f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * @param uploadChangesOnly if set, specify that the sync should only send
31417e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff     *   up local changes.  This is typically used for a local sync, a user override of
31427e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff     *   too many deletions, or a sync after a calendar is unselected.
31437e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff     * @param url the url feed for the calendar to sync (may be null, in which case a poll of
31447e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff     *   all feeds is done.)
31459f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     */
31469f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    void scheduleSync(Account account, boolean uploadChangesOnly, String url) {
31479f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        Bundle extras = new Bundle();
31487e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        if (uploadChangesOnly) {
31497e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff            extras.putBoolean(ContentResolver.SYNC_EXTRAS_UPLOAD, uploadChangesOnly);
31507e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        }
31519f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        if (url != null) {
31529f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            extras.putString("feed", url);
31539f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
3154c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert        ContentResolver.requestSync(account, Calendars.CONTENT_URI.getAuthority(),
3155b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                extras);
31569f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
31579f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
31587e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff    private static void createEventsView(SQLiteDatabase db) {
31597e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        db.execSQL("DROP VIEW IF EXISTS " + Views.EVENTS + ";");
31607e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        String eventsSelect = "SELECT "
3161b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + Tables.EVENTS + "." + CalendarContract.Events._ID
3162b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                        + " AS " + CalendarContract.Events._ID + ","
3163b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Events.TITLE + ","
3164b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Events.DESCRIPTION + ","
3165b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Events.EVENT_LOCATION + ","
3166b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Events.EVENT_COLOR + ","
3167387535fec9f646e0b7acb82d5354f2b5ebee4395RoboErik                + CalendarContract.Events.EVENT_COLOR_KEY + ","
3168b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Events.STATUS + ","
3169b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Events.SELF_ATTENDEE_STATUS + ","
3170b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Events.DTSTART + ","
3171b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Events.DTEND + ","
3172b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Events.DURATION + ","
3173b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Events.EVENT_TIMEZONE + ","
3174b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Events.EVENT_END_TIMEZONE + ","
3175b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Events.ALL_DAY + ","
3176b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Events.ACCESS_LEVEL + ","
3177b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Events.AVAILABILITY + ","
3178b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Events.HAS_ALARM + ","
3179b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Events.HAS_EXTENDED_PROPERTIES + ","
3180b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Events.RRULE + ","
3181b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Events.RDATE + ","
3182b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Events.EXRULE + ","
3183b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Events.EXDATE + ","
3184b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Events.ORIGINAL_SYNC_ID + ","
3185b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Events.ORIGINAL_ID + ","
3186b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Events.ORIGINAL_INSTANCE_TIME + ","
3187b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Events.ORIGINAL_ALL_DAY + ","
3188b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Events.LAST_DATE + ","
3189b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Events.HAS_ATTENDEE_DATA + ","
3190b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Events.CALENDAR_ID + ","
3191b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Events.GUESTS_CAN_INVITE_OTHERS + ","
3192b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Events.GUESTS_CAN_MODIFY + ","
3193b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Events.GUESTS_CAN_SEE_GUESTS + ","
3194b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Events.ORGANIZER + ","
3195b2695bf3cfb173c4c5ba7bfd3c93ba8a51d65810Alon Albert                + "COALESCE("
3196b2695bf3cfb173c4c5ba7bfd3c93ba8a51d65810Alon Albert                + Events.IS_ORGANIZER + ", " + Events.ORGANIZER + " = " + Calendars.OWNER_ACCOUNT
3197b2695bf3cfb173c4c5ba7bfd3c93ba8a51d65810Alon Albert                + ") AS " + Events.IS_ORGANIZER + ","
3198c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan                + CalendarContract.Events.CUSTOM_APP_PACKAGE + ","
3199c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan                + CalendarContract.Events.CUSTOM_APP_URI + ","
3200501e60bcb1b519d80723f7b64ba60bd079b8ec8dSara Ting                + CalendarContract.Events.UID_2445 + ","
3201b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Events.SYNC_DATA1 + ","
3202b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Events.SYNC_DATA2 + ","
3203b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Events.SYNC_DATA3 + ","
3204b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Events.SYNC_DATA4 + ","
3205b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Events.SYNC_DATA5 + ","
3206b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Events.SYNC_DATA6 + ","
3207b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Events.SYNC_DATA7 + ","
3208b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Events.SYNC_DATA8 + ","
3209b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Events.SYNC_DATA9 + ","
3210b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Events.SYNC_DATA10 + ","
3211b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + Tables.EVENTS + "." + CalendarContract.Events.DELETED
3212b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + " AS " + CalendarContract.Events.DELETED + ","
3213b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + Tables.EVENTS + "." + CalendarContract.Events._SYNC_ID
3214b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + " AS " + CalendarContract.Events._SYNC_ID + ","
3215b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + Tables.EVENTS + "." + CalendarContract.Events.DIRTY
3216b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + " AS " + CalendarContract.Events.DIRTY + ","
32177a2531a4b68e9efe14353cc7f4a64a8c5613e5d3Alon Albert                + Tables.EVENTS + "." + Events.MUTATORS
32187a2531a4b68e9efe14353cc7f4a64a8c5613e5d3Alon Albert                + " AS " + Events.MUTATORS + ","
3219b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Events.LAST_SYNCED + ","
3220c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                + Tables.CALENDARS + "." + Calendars.ACCOUNT_NAME
3221b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + " AS " + CalendarContract.Events.ACCOUNT_NAME + ","
3222c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                + Tables.CALENDARS + "." + Calendars.ACCOUNT_TYPE
3223b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + " AS " + CalendarContract.Events.ACCOUNT_TYPE + ","
3224c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                + Calendars.CALENDAR_TIME_ZONE + ","
3225c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                + Calendars.CALENDAR_DISPLAY_NAME + ","
3226c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                + Calendars.CALENDAR_LOCATION + ","
3227c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                + Calendars.VISIBLE + ","
3228c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                + Calendars.CALENDAR_COLOR + ","
3229c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                + Calendars.CALENDAR_COLOR_KEY + ","
3230c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                + Calendars.CALENDAR_ACCESS_LEVEL + ","
3231c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                + Calendars.MAX_REMINDERS + ","
3232c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                + Calendars.ALLOWED_REMINDERS + ","
3233c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                + Calendars.ALLOWED_ATTENDEE_TYPES + ","
3234c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                + Calendars.ALLOWED_AVAILABILITY + ","
3235c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                + Calendars.CAN_ORGANIZER_RESPOND + ","
3236c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                + Calendars.CAN_MODIFY_TIME_ZONE + ","
3237c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                + Calendars.CAN_PARTIALLY_UPDATE + ","
3238c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                + Calendars.CAL_SYNC1 + ","
3239c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                + Calendars.CAL_SYNC2 + ","
3240c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                + Calendars.CAL_SYNC3 + ","
3241c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                + Calendars.CAL_SYNC4 + ","
3242c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                + Calendars.CAL_SYNC5 + ","
3243c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                + Calendars.CAL_SYNC6 + ","
3244c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                + Calendars.CAL_SYNC7 + ","
3245c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                + Calendars.CAL_SYNC8 + ","
3246c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                + Calendars.CAL_SYNC9 + ","
3247c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                + Calendars.CAL_SYNC10 + ","
3248c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                + Calendars.OWNER_ACCOUNT + ","
3249c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                + Calendars.SYNC_EVENTS  + ","
3250c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                + "ifnull(" + Events.EVENT_COLOR + "," + Calendars.CALENDAR_COLOR + ") AS "
3251c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                + Events.DISPLAY_COLOR
32527e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff                + " FROM " + Tables.EVENTS + " JOIN " + Tables.CALENDARS
3253c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                + " ON (" + Tables.EVENTS + "." + Events.CALENDAR_ID
3254c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                + "=" + Tables.CALENDARS + "." + Calendars._ID
32557e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff                + ")";
32567e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff
32577e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        db.execSQL("CREATE VIEW " + Views.EVENTS + " AS " + eventsSelect);
32587e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff    }
3259d39cfe09aa7e752cdc7512ae58d90d49d4b5ef9eKen Shirriff
3260d39cfe09aa7e752cdc7512ae58d90d49d4b5ef9eKen Shirriff    /**
3261d39cfe09aa7e752cdc7512ae58d90d49d4b5ef9eKen Shirriff     * Extracts the calendar email from a calendar feed url.
3262d39cfe09aa7e752cdc7512ae58d90d49d4b5ef9eKen Shirriff     * @param feed the calendar feed url
3263d39cfe09aa7e752cdc7512ae58d90d49d4b5ef9eKen Shirriff     * @return the calendar email that is in the feed url or null if it can't
3264d39cfe09aa7e752cdc7512ae58d90d49d4b5ef9eKen Shirriff     * find the email address.
3265d39cfe09aa7e752cdc7512ae58d90d49d4b5ef9eKen Shirriff     * TODO: this is duplicated in CalendarSyncAdapter; move to a library
3266d39cfe09aa7e752cdc7512ae58d90d49d4b5ef9eKen Shirriff     */
3267d39cfe09aa7e752cdc7512ae58d90d49d4b5ef9eKen Shirriff    public static String calendarEmailAddressFromFeedUrl(String feed) {
3268d39cfe09aa7e752cdc7512ae58d90d49d4b5ef9eKen Shirriff        // Example feed url:
3269d39cfe09aa7e752cdc7512ae58d90d49d4b5ef9eKen Shirriff        // https://www.google.com/calendar/feeds/foo%40gmail.com/private/full-noattendees
3270d39cfe09aa7e752cdc7512ae58d90d49d4b5ef9eKen Shirriff        String[] pathComponents = feed.split("/");
3271d39cfe09aa7e752cdc7512ae58d90d49d4b5ef9eKen Shirriff        if (pathComponents.length > 5 && "feeds".equals(pathComponents[4])) {
3272d39cfe09aa7e752cdc7512ae58d90d49d4b5ef9eKen Shirriff            try {
3273d39cfe09aa7e752cdc7512ae58d90d49d4b5ef9eKen Shirriff                return URLDecoder.decode(pathComponents[5], "UTF-8");
3274d39cfe09aa7e752cdc7512ae58d90d49d4b5ef9eKen Shirriff            } catch (UnsupportedEncodingException e) {
3275d39cfe09aa7e752cdc7512ae58d90d49d4b5ef9eKen Shirriff                Log.e(TAG, "unable to url decode the email address in calendar " + feed);
3276d39cfe09aa7e752cdc7512ae58d90d49d4b5ef9eKen Shirriff                return null;
3277d39cfe09aa7e752cdc7512ae58d90d49d4b5ef9eKen Shirriff            }
3278d39cfe09aa7e752cdc7512ae58d90d49d4b5ef9eKen Shirriff        }
3279d39cfe09aa7e752cdc7512ae58d90d49d4b5ef9eKen Shirriff
3280d39cfe09aa7e752cdc7512ae58d90d49d4b5ef9eKen Shirriff        Log.e(TAG, "unable to find the email address in calendar " + feed);
3281d39cfe09aa7e752cdc7512ae58d90d49d4b5ef9eKen Shirriff        return null;
3282d39cfe09aa7e752cdc7512ae58d90d49d4b5ef9eKen Shirriff    }
32831b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio
32841b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio    /**
32851b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio     * Get a "allcalendars" url from a "private/full" or "private/free-busy" url
32861b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio     * @param url
32871b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio     * @return the rewritten Url
32881b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio     *
32891b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio     * For example:
32901b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio     *
32911b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio     *      http://www.google.com/calendar/feeds/joe%40joe.com/private/full
32921b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio     *      http://www.google.com/calendar/feeds/joe%40joe.com/private/free-busy
32931b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio     *
32941b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio     * will be rewriten into:
32951b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio     *
32961b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio     *      http://www.google.com/calendar/feeds/default/allcalendars/full/joe%40joe.com
32971b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio     *      http://www.google.com/calendar/feeds/default/allcalendars/full/joe%40joe.com
32981b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio     */
32991b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio    private static String getAllCalendarsUrlFromEventsUrl(String url) {
33001b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio        if (url == null) {
33011b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio            if (Log.isLoggable(TAG, Log.DEBUG)) {
33021b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio                Log.d(TAG, "Cannot get AllCalendars url from a NULL url");
33031b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio            }
33041b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio            return null;
33051b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio        }
33061b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio        if (url.contains("/private/full")) {
33071b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio            return url.replace("/private/full", "").
33081b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio                    replace("/calendar/feeds", "/calendar/feeds/default/allcalendars/full");
33091b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio        }
33101b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio        if (url.contains("/private/free-busy")) {
33111b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio            return url.replace("/private/free-busy", "").
33121b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio                    replace("/calendar/feeds", "/calendar/feeds/default/allcalendars/full");
33131b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio        }
33141b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio        // Just log as we dont recognize the provided Url
33151b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio        if (Log.isLoggable(TAG, Log.DEBUG)) {
33161b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio            Log.d(TAG, "Cannot get AllCalendars url from the following url: " + url);
33171b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio        }
33181b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio        return null;
33191b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio    }
33201b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio
33211b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio    /**
33221b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio     * Get "selfUrl" from "events url"
33231b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio     * @param url the Events url (either "private/full" or "private/free-busy"
33241b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio     * @return the corresponding allcalendar url
33251b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio     */
33261b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio    private static String getSelfUrlFromEventsUrl(String url) {
33271b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio        return rewriteUrlFromHttpToHttps(getAllCalendarsUrlFromEventsUrl(url));
33281b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio    }
33291b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio
33301b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio    /**
33311b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio     * Get "editUrl" from "events url"
33321b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio     * @param url the Events url (either "private/full" or "private/free-busy"
33331b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio     * @return the corresponding allcalendar url
33341b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio     */
33351b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio    private static String getEditUrlFromEventsUrl(String url) {
33361b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio        return rewriteUrlFromHttpToHttps(getAllCalendarsUrlFromEventsUrl(url));
33371b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio    }
33381b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio
33391b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio    /**
33401b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio     * Rewrite the url from "http" to "https" scheme
33411b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio     * @param url the url to rewrite
33421b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio     * @return the rewritten URL
33431b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio     */
33441b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio    private static String rewriteUrlFromHttpToHttps(String url) {
33451b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio        if (url == null) {
33461b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio            if (Log.isLoggable(TAG, Log.DEBUG)) {
33471b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio                Log.d(TAG, "Cannot rewrite a NULL url");
33481b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio            }
33491b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio            return null;
33501b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio        }
33511b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio        if (url.startsWith(SCHEMA_HTTPS)) {
33521b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio            return url;
33531b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio        }
33541b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio        if (!url.startsWith(SCHEMA_HTTP)) {
33551b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio            throw new IllegalArgumentException("invalid url parameter, unknown scheme: " + url);
33561b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio        }
33571b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio        return SCHEMA_HTTPS + url.substring(SCHEMA_HTTP.length());
33581b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio    }
33599ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert
33601c72909abbfe7559bcc880c339399f1eaa0478f3Andy McFadden    /**
33611c72909abbfe7559bcc880c339399f1eaa0478f3Andy McFadden     * Duplicates an event and its associated tables (Attendees, Reminders, ExtendedProperties).
33621c72909abbfe7559bcc880c339399f1eaa0478f3Andy McFadden     * <p>
33631c72909abbfe7559bcc880c339399f1eaa0478f3Andy McFadden     * Does not create a duplicate if the Calendar's "canPartiallyUpdate" is 0 or the Event's
33641c72909abbfe7559bcc880c339399f1eaa0478f3Andy McFadden     * "dirty" is 1 (so we don't create more than one duplicate).
33651c72909abbfe7559bcc880c339399f1eaa0478f3Andy McFadden     *
33661c72909abbfe7559bcc880c339399f1eaa0478f3Andy McFadden     * @param id The _id of the event to duplicate.
33671c72909abbfe7559bcc880c339399f1eaa0478f3Andy McFadden     */
33689ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert    protected void duplicateEvent(final long id) {
33699ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert        final SQLiteDatabase db = getWritableDatabase();
3370b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        final long canPartiallyUpdate = DatabaseUtils.longForQuery(db, "SELECT "
3371c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                + Calendars.CAN_PARTIALLY_UPDATE + " FROM " + Views.EVENTS
3372b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + " WHERE " + Events._ID + " = ?", new String[] {
3373b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik            String.valueOf(id)
3374b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik        });
33759ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert        if (canPartiallyUpdate == 0) {
33769ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert            return;
33779ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert        }
33789ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert
33799ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert        db.execSQL("INSERT INTO " + CalendarDatabaseHelper.Tables.EVENTS
33809ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                + "  (" + LAST_SYNCED_EVENT_COLUMNS + ","
33819ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                +         Events.DIRTY + "," + Events.LAST_SYNCED + ")"
33829ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                + " SELECT " + LAST_SYNCED_EVENT_COLUMNS + ", 0, 1"
33839ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                + " FROM " + Tables.EVENTS
33849ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                + " WHERE "  + Events._ID + " = ? AND " + Events.DIRTY + " = ?",
33859ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                new Object[]{
33869ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                        id,
33879ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                        0, // Events.DIRTY
33889ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                });
33899ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert        final long newId = DatabaseUtils.longForQuery(
33909ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                db, "SELECT CASE changes() WHEN 0 THEN -1 ELSE last_insert_rowid() END", null);
33919ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert        if (newId < 0) {
33929ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert            return;
33939ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert        }
33949ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert
33959ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert        if (Log.isLoggable(TAG, Log.VERBOSE)) {
33969ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert            Log.v(TAG, "Duplicating event " + id + " into new event " + newId);
33979ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert        }
33989ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert
3399bcba82631ab0ee16efe58f0e0b0b9c18d93a6fd2Andy McFadden        copyEventRelatedTables(db, newId, id);
3400bcba82631ab0ee16efe58f0e0b0b9c18d93a6fd2Andy McFadden    }
3401bcba82631ab0ee16efe58f0e0b0b9c18d93a6fd2Andy McFadden
34021c72909abbfe7559bcc880c339399f1eaa0478f3Andy McFadden    /**
34031c72909abbfe7559bcc880c339399f1eaa0478f3Andy McFadden     * Makes a copy of the Attendees, Reminders, and ExtendedProperties rows associated with
34041c72909abbfe7559bcc880c339399f1eaa0478f3Andy McFadden     * a specific event.
34051c72909abbfe7559bcc880c339399f1eaa0478f3Andy McFadden     *
34061c72909abbfe7559bcc880c339399f1eaa0478f3Andy McFadden     * @param db The database.
34071c72909abbfe7559bcc880c339399f1eaa0478f3Andy McFadden     * @param newId The ID of the new event.
34081c72909abbfe7559bcc880c339399f1eaa0478f3Andy McFadden     * @param id The ID of the old event.
34091c72909abbfe7559bcc880c339399f1eaa0478f3Andy McFadden     */
3410bcba82631ab0ee16efe58f0e0b0b9c18d93a6fd2Andy McFadden    static void copyEventRelatedTables(SQLiteDatabase db, long newId, long id) {
34119ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert        db.execSQL("INSERT INTO " + Tables.REMINDERS
3412b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + " ( "  + CalendarContract.Reminders.EVENT_ID + ", "
3413b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                        + LAST_SYNCED_REMINDER_COLUMNS + ") "
34149ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                + "SELECT ?," + LAST_SYNCED_REMINDER_COLUMNS
34159ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                + " FROM " + Tables.REMINDERS
3416b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + " WHERE " + CalendarContract.Reminders.EVENT_ID + " = ?",
34179ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                new Object[] {newId, id});
34189ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert        db.execSQL("INSERT INTO "
34199ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                + Tables.ATTENDEES
3420b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + " (" + CalendarContract.Attendees.EVENT_ID + ","
3421b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                        + LAST_SYNCED_ATTENDEE_COLUMNS + ") "
34229ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                + "SELECT ?," + LAST_SYNCED_ATTENDEE_COLUMNS + " FROM " + Tables.ATTENDEES
3423b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + " WHERE " + CalendarContract.Attendees.EVENT_ID + " = ?",
34249ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                new Object[] {newId, id});
34259ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert        db.execSQL("INSERT INTO " + Tables.EXTENDED_PROPERTIES
3426b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + " (" + CalendarContract.ExtendedProperties.EVENT_ID + ","
34279ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                + LAST_SYNCED_EXTENDED_PROPERTY_COLUMNS + ") "
34289ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                + "SELECT ?, " + LAST_SYNCED_EXTENDED_PROPERTY_COLUMNS
34299ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                + " FROM " + Tables.EXTENDED_PROPERTIES
3430b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + " WHERE " + CalendarContract.ExtendedProperties.EVENT_ID + " = ?",
34319ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                new Object[]{newId, id});
34329ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert    }
34339ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert
34349ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert    protected void removeDuplicateEvent(final long id) {
34359ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert        final SQLiteDatabase db = getWritableDatabase();
34369ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert        final Cursor cursor = db.rawQuery("SELECT " + Events._ID + " FROM " + Tables.EVENTS
34379ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                + " WHERE " + Events._SYNC_ID
34389ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                + " = (SELECT " + Events._SYNC_ID
34399ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                + " FROM " + Tables.EVENTS
34409ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                + " WHERE " + Events._ID + " = ?) "
34419ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                + "AND " + Events.LAST_SYNCED + " = ?",
34429ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                new String[]{
34439ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                        String.valueOf(id),
34449ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                        "1", // Events.LAST_SYNCED
34459ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                });
34469ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert        try {
34479ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert            // there should only be at most one but this can't hurt
34489ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert            if (cursor.moveToNext()) {
34499ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                final long dupId = cursor.getLong(0);
34509ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert
34519ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                if (Log.isLoggable(TAG, Log.VERBOSE)) {
34529ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                    Log.v(TAG, "Removing duplicate event " + dupId + " of original event " + id);
34539ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                }
34549ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                // triggers will clean up related tables.
34559ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                db.execSQL("DELETE FROM Events WHERE " + Events._ID + " = ?", new Object[]{dupId});
34569ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert            }
34579ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert        } finally {
34589ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert          cursor.close();
34599ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert        }
34609ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert    }
34619f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff}
3462