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;
27d3b51e172bba03af7d2fcc3559cfa73b6ce60095Alon Albertimport android.database.sqlite.SQLiteDoneException;
28a6357118c223d00ed722ecd40ecdda92d705d211Erikimport android.database.sqlite.SQLiteException;
299f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriffimport android.database.sqlite.SQLiteOpenHelper;
309f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriffimport android.os.Bundle;
31b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErikimport android.provider.CalendarContract;
32b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErikimport android.provider.CalendarContract.Attendees;
332f251c778c06d21ed7693a70f4a1268ff929242eRoboErikimport android.provider.CalendarContract.Calendars;
342f251c778c06d21ed7693a70f4a1268ff929242eRoboErikimport android.provider.CalendarContract.Colors;
35b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErikimport android.provider.CalendarContract.Events;
36b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErikimport android.provider.CalendarContract.Reminders;
37d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriffimport android.provider.SyncStateContract;
387b40dde3168f4af2c757cb43955aa3bfe1668666Erikimport android.text.TextUtils;
39ae4f20e120d3107cef20be860a612c9c23816295Erikimport android.text.format.Time;
409f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriffimport android.util.Log;
419f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
42b2695bf3cfb173c4c5ba7bfd3c93ba8a51d65810Alon Albertimport com.android.common.content.SyncStateContentProviderHelper;
43b2695bf3cfb173c4c5ba7bfd3c93ba8a51d65810Alon Albertimport com.google.common.annotations.VisibleForTesting;
44b2695bf3cfb173c4c5ba7bfd3c93ba8a51d65810Alon Albert
45d39cfe09aa7e752cdc7512ae58d90d49d4b5ef9eKen Shirriffimport java.io.UnsupportedEncodingException;
46162c7c9bbd53b623fbe913b376e7f7f42915bb59Marc Blankimport java.net.URLDecoder;
47315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglioimport java.util.TimeZone;
48d39cfe09aa7e752cdc7512ae58d90d49d4b5ef9eKen Shirriff
499f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff/**
509f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff * Database helper for calendar. Designed as a singleton to make sure that all
519f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff * {@link android.content.ContentProvider} users get the same reference.
529f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff */
539f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff/* package */ class CalendarDatabaseHelper extends SQLiteOpenHelper {
5481d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang
559f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private static final String TAG = "CalendarDatabaseHelper";
569f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
5781d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang    private static final boolean LOGD = false;
5881d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang
59c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan    @VisibleForTesting
60c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan    public boolean mInTestMode = false;
61c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan
62ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff    private static final String DATABASE_NAME = "calendar.db";
639f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
647b40dde3168f4af2c757cb43955aa3bfe1668666Erik    private static final int DAY_IN_SECONDS = 24 * 60 * 60;
657b40dde3168f4af2c757cb43955aa3bfe1668666Erik
669f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    // Note: if you update the version number, you must also update the code
679f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    // in upgradeDatabase() to modify the database (gracefully, if possible).
680d8699eedb0f3bcec1854b9753ae59154a122726Michael Chan    //
690d8699eedb0f3bcec1854b9753ae59154a122726Michael Chan    //  xx Froyo and prior
700d8699eedb0f3bcec1854b9753ae59154a122726Michael Chan    // 1xx for Gingerbread,
710d8699eedb0f3bcec1854b9753ae59154a122726Michael Chan    // 2xx for Honeycomb
720d8699eedb0f3bcec1854b9753ae59154a122726Michael Chan    // 3xx for ICS
730d8699eedb0f3bcec1854b9753ae59154a122726Michael Chan    // 4xx for JB
74b2695bf3cfb173c4c5ba7bfd3c93ba8a51d65810Alon Albert    // 5xx for JB MR1
75b2695bf3cfb173c4c5ba7bfd3c93ba8a51d65810Alon Albert    // 6xx for K
760d8699eedb0f3bcec1854b9753ae59154a122726Michael Chan    // Bump this to the next hundred at each major release.
777a2531a4b68e9efe14353cc7f4a64a8c5613e5d3Alon Albert    static final int DATABASE_VERSION = 600;
789f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
79d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff    private static final int PRE_FROYO_SYNC_STATE_VERSION = 3;
80d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff
819ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert    // columns used to duplicate an event row
8202f97c538fc46a08d857d2c807c76fd0eec12493RoboErik    private static final String LAST_SYNCED_EVENT_COLUMNS =
8302f97c538fc46a08d857d2c807c76fd0eec12493RoboErik            Events._SYNC_ID + "," +
8402f97c538fc46a08d857d2c807c76fd0eec12493RoboErik            Events.CALENDAR_ID + "," +
8502f97c538fc46a08d857d2c807c76fd0eec12493RoboErik            Events.TITLE + "," +
8602f97c538fc46a08d857d2c807c76fd0eec12493RoboErik            Events.EVENT_LOCATION + "," +
8702f97c538fc46a08d857d2c807c76fd0eec12493RoboErik            Events.DESCRIPTION + "," +
8802f97c538fc46a08d857d2c807c76fd0eec12493RoboErik            Events.EVENT_COLOR + "," +
89387535fec9f646e0b7acb82d5354f2b5ebee4395RoboErik            Events.EVENT_COLOR_KEY + "," +
9002f97c538fc46a08d857d2c807c76fd0eec12493RoboErik            Events.STATUS + "," +
9102f97c538fc46a08d857d2c807c76fd0eec12493RoboErik            Events.SELF_ATTENDEE_STATUS + "," +
9202f97c538fc46a08d857d2c807c76fd0eec12493RoboErik            Events.DTSTART + "," +
9302f97c538fc46a08d857d2c807c76fd0eec12493RoboErik            Events.DTEND + "," +
9402f97c538fc46a08d857d2c807c76fd0eec12493RoboErik            Events.EVENT_TIMEZONE + "," +
9502f97c538fc46a08d857d2c807c76fd0eec12493RoboErik            Events.EVENT_END_TIMEZONE + "," +
9602f97c538fc46a08d857d2c807c76fd0eec12493RoboErik            Events.DURATION + "," +
9702f97c538fc46a08d857d2c807c76fd0eec12493RoboErik            Events.ALL_DAY + "," +
9802f97c538fc46a08d857d2c807c76fd0eec12493RoboErik            Events.ACCESS_LEVEL + "," +
9902f97c538fc46a08d857d2c807c76fd0eec12493RoboErik            Events.AVAILABILITY + "," +
10002f97c538fc46a08d857d2c807c76fd0eec12493RoboErik            Events.HAS_ALARM + "," +
10102f97c538fc46a08d857d2c807c76fd0eec12493RoboErik            Events.HAS_EXTENDED_PROPERTIES + "," +
10202f97c538fc46a08d857d2c807c76fd0eec12493RoboErik            Events.RRULE + "," +
10302f97c538fc46a08d857d2c807c76fd0eec12493RoboErik            Events.RDATE + "," +
10402f97c538fc46a08d857d2c807c76fd0eec12493RoboErik            Events.EXRULE + "," +
10502f97c538fc46a08d857d2c807c76fd0eec12493RoboErik            Events.EXDATE + "," +
10602f97c538fc46a08d857d2c807c76fd0eec12493RoboErik            Events.ORIGINAL_SYNC_ID + "," +
10702f97c538fc46a08d857d2c807c76fd0eec12493RoboErik            Events.ORIGINAL_ID + "," +
10802f97c538fc46a08d857d2c807c76fd0eec12493RoboErik            Events.ORIGINAL_INSTANCE_TIME + "," +
10902f97c538fc46a08d857d2c807c76fd0eec12493RoboErik            Events.ORIGINAL_ALL_DAY + "," +
11002f97c538fc46a08d857d2c807c76fd0eec12493RoboErik            Events.LAST_DATE + "," +
11102f97c538fc46a08d857d2c807c76fd0eec12493RoboErik            Events.HAS_ATTENDEE_DATA + "," +
11202f97c538fc46a08d857d2c807c76fd0eec12493RoboErik            Events.GUESTS_CAN_MODIFY + "," +
11302f97c538fc46a08d857d2c807c76fd0eec12493RoboErik            Events.GUESTS_CAN_INVITE_OTHERS + "," +
11402f97c538fc46a08d857d2c807c76fd0eec12493RoboErik            Events.GUESTS_CAN_SEE_GUESTS + "," +
115c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan            Events.ORGANIZER + "," +
116b2695bf3cfb173c4c5ba7bfd3c93ba8a51d65810Alon Albert            Events.IS_ORGANIZER + "," +
117c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan            Events.CUSTOM_APP_PACKAGE + "," +
118501e60bcb1b519d80723f7b64ba60bd079b8ec8dSara Ting            Events.CUSTOM_APP_URI + "," +
119501e60bcb1b519d80723f7b64ba60bd079b8ec8dSara Ting            Events.UID_2445;
1209ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert
1219ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert    // columns used to duplicate a reminder row
12202f97c538fc46a08d857d2c807c76fd0eec12493RoboErik    private static final String LAST_SYNCED_REMINDER_COLUMNS =
123470aa5bc291ca33d51dda356f38ac2954026da9aAlon Albert            Reminders.MINUTES + "," +
124470aa5bc291ca33d51dda356f38ac2954026da9aAlon Albert            Reminders.METHOD;
1259ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert
1269ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert    // columns used to duplicate an attendee row
12702f97c538fc46a08d857d2c807c76fd0eec12493RoboErik    private static final String LAST_SYNCED_ATTENDEE_COLUMNS =
128470aa5bc291ca33d51dda356f38ac2954026da9aAlon Albert            Attendees.ATTENDEE_NAME + "," +
129470aa5bc291ca33d51dda356f38ac2954026da9aAlon Albert            Attendees.ATTENDEE_EMAIL + "," +
130470aa5bc291ca33d51dda356f38ac2954026da9aAlon Albert            Attendees.ATTENDEE_STATUS + "," +
131470aa5bc291ca33d51dda356f38ac2954026da9aAlon Albert            Attendees.ATTENDEE_RELATIONSHIP + "," +
132bafe9de156292f65b1079dd1eb586669f573d9e6Michael Chan            Attendees.ATTENDEE_TYPE + "," +
133bafe9de156292f65b1079dd1eb586669f573d9e6Michael Chan            Attendees.ATTENDEE_IDENTITY + "," +
134bafe9de156292f65b1079dd1eb586669f573d9e6Michael Chan            Attendees.ATTENDEE_ID_NAMESPACE;
1359ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert
1369ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert    // columns used to duplicate an extended property row
13702f97c538fc46a08d857d2c807c76fd0eec12493RoboErik    private static final String LAST_SYNCED_EXTENDED_PROPERTY_COLUMNS =
138b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik            CalendarContract.ExtendedProperties.NAME + "," +
139b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik            CalendarContract.ExtendedProperties.VALUE;
1409ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert
1417cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio    public interface Tables {
1427cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio        public static final String CALENDARS = "Calendars";
1437cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio        public static final String EVENTS = "Events";
1447cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio        public static final String EVENTS_RAW_TIMES = "EventsRawTimes";
1457cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio        public static final String INSTANCES = "Instances";
1467cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio        public static final String ATTENDEES = "Attendees";
1477cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio        public static final String REMINDERS = "Reminders";
1487cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio        public static final String CALENDAR_ALERTS = "CalendarAlerts";
1497cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio        public static final String EXTENDED_PROPERTIES = "ExtendedProperties";
1507cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio        public static final String CALENDAR_META_DATA = "CalendarMetaData";
1517cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio        public static final String CALENDAR_CACHE = "CalendarCache";
1527cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio        public static final String SYNC_STATE = "_sync_state";
1537cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio        public static final String SYNC_STATE_META = "_sync_state_metadata";
1542f251c778c06d21ed7693a70f4a1268ff929242eRoboErik        public static final String COLORS = "Colors";
1557cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio    }
1567cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio
1577cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio    public interface Views {
158bcba82631ab0ee16efe58f0e0b0b9c18d93a6fd2Andy McFadden        public static final String EVENTS = "view_events";
1597cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio    }
1607cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio
161d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff    // Copied from SyncStateContentProviderHelper.  Don't really want to make them public there.
162d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff    private static final String SYNC_STATE_META_VERSION_COLUMN = "version";
163d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff
1647cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio    // This needs to be done when all the tables are already created
1657cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio    private static final String EVENTS_CLEANUP_TRIGGER_SQL =
1667cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio            "DELETE FROM " + Tables.INSTANCES +
167b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                " WHERE "+ CalendarContract.Instances.EVENT_ID + "=" +
168b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                    "old." + CalendarContract.Events._ID + ";" +
1697cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio            "DELETE FROM " + Tables.EVENTS_RAW_TIMES +
170b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                " WHERE " + CalendarContract.EventsRawTimes.EVENT_ID + "=" +
171b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                    "old." + CalendarContract.Events._ID + ";" +
1727cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio            "DELETE FROM " + Tables.ATTENDEES +
173b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                " WHERE " + CalendarContract.Attendees.EVENT_ID + "=" +
174b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                    "old." + CalendarContract.Events._ID + ";" +
1757cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio            "DELETE FROM " + Tables.REMINDERS +
176b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                " WHERE " + CalendarContract.Reminders.EVENT_ID + "=" +
177b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                    "old." + CalendarContract.Events._ID + ";" +
1787cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio            "DELETE FROM " + Tables.CALENDAR_ALERTS +
179b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                " WHERE " + CalendarContract.CalendarAlerts.EVENT_ID + "=" +
180b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                    "old." + CalendarContract.Events._ID + ";" +
1817cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio            "DELETE FROM " + Tables.EXTENDED_PROPERTIES +
182b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                " WHERE " + CalendarContract.ExtendedProperties.EVENT_ID + "=" +
183b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                    "old." + CalendarContract.Events._ID + ";";
1847cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio
18534c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik    // This ensures any exceptions based on an event get their original_sync_id
18634c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik    // column set when an the _sync_id is set.
18734c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik    private static final String EVENTS_ORIGINAL_SYNC_TRIGGER_SQL =
18834c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik            "UPDATE " + Tables.EVENTS +
18934c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik                " SET " + Events.ORIGINAL_SYNC_ID + "=new." + Events._SYNC_ID +
19034c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik                " WHERE " + Events.ORIGINAL_ID + "=old." + Events._ID + ";";
19134c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik
19234c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik    private static final String SYNC_ID_UPDATE_TRIGGER_NAME = "original_sync_update";
19334c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik    private static final String CREATE_SYNC_ID_UPDATE_TRIGGER =
19434c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik            "CREATE TRIGGER " + SYNC_ID_UPDATE_TRIGGER_NAME + " UPDATE OF " + Events._SYNC_ID +
19534c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik            " ON " + Tables.EVENTS +
19634c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik            " BEGIN " +
19734c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik                EVENTS_ORIGINAL_SYNC_TRIGGER_SQL +
19834c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik            " END";
19934c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik
2007cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio    private static final String CALENDAR_CLEANUP_TRIGGER_SQL = "DELETE FROM " + Tables.EVENTS +
201b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik            " WHERE " + CalendarContract.Events.CALENDAR_ID + "=" +
202b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                "old." + CalendarContract.Events._ID + ";";
2037cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio
2042f251c778c06d21ed7693a70f4a1268ff929242eRoboErik    private static final String CALENDAR_UPDATE_COLOR_TRIGGER_SQL = "UPDATE " + Tables.CALENDARS
2052f251c778c06d21ed7693a70f4a1268ff929242eRoboErik            + " SET calendar_color=(SELECT " + Colors.COLOR + " FROM " + Tables.COLORS + " WHERE "
2062f251c778c06d21ed7693a70f4a1268ff929242eRoboErik            + Colors.ACCOUNT_NAME + "=" + "new." + Calendars.ACCOUNT_NAME + " AND "
2072f251c778c06d21ed7693a70f4a1268ff929242eRoboErik            + Colors.ACCOUNT_TYPE + "=" + "new." + Calendars.ACCOUNT_TYPE + " AND "
208c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert            + Colors.COLOR_KEY + "=" + "new." + Calendars.CALENDAR_COLOR_KEY + " AND "
209c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert            + Colors.COLOR_TYPE + "=" + Colors.TYPE_CALENDAR + ") "
2102f251c778c06d21ed7693a70f4a1268ff929242eRoboErik            + " WHERE " + Calendars._ID + "=" + "old." + Calendars._ID
2112f251c778c06d21ed7693a70f4a1268ff929242eRoboErik            + ";";
2122f251c778c06d21ed7693a70f4a1268ff929242eRoboErik    private static final String CALENDAR_COLOR_UPDATE_TRIGGER_NAME = "calendar_color_update";
2132f251c778c06d21ed7693a70f4a1268ff929242eRoboErik    private static final String CREATE_CALENDAR_COLOR_UPDATE_TRIGGER = "CREATE TRIGGER "
214387535fec9f646e0b7acb82d5354f2b5ebee4395RoboErik            + CALENDAR_COLOR_UPDATE_TRIGGER_NAME + " UPDATE OF " + Calendars.CALENDAR_COLOR_KEY
215387535fec9f646e0b7acb82d5354f2b5ebee4395RoboErik            + " ON " + Tables.CALENDARS + " WHEN new." + Calendars.CALENDAR_COLOR_KEY
2162f251c778c06d21ed7693a70f4a1268ff929242eRoboErik            + " NOT NULL BEGIN " + CALENDAR_UPDATE_COLOR_TRIGGER_SQL + " END";
2172f251c778c06d21ed7693a70f4a1268ff929242eRoboErik
2182f251c778c06d21ed7693a70f4a1268ff929242eRoboErik    private static final String EVENT_UPDATE_COLOR_TRIGGER_SQL = "UPDATE " + Tables.EVENTS
2192f251c778c06d21ed7693a70f4a1268ff929242eRoboErik            + " SET eventColor=(SELECT " + Colors.COLOR + " FROM " + Tables.COLORS + " WHERE "
2202f251c778c06d21ed7693a70f4a1268ff929242eRoboErik            + Colors.ACCOUNT_NAME + "=" + "(SELECT " + Calendars.ACCOUNT_NAME + " FROM "
2212f251c778c06d21ed7693a70f4a1268ff929242eRoboErik            + Tables.CALENDARS + " WHERE " + Calendars._ID + "=new." + Events.CALENDAR_ID
2222f251c778c06d21ed7693a70f4a1268ff929242eRoboErik            + ") AND " + Colors.ACCOUNT_TYPE + "=" + "(SELECT " + Calendars.ACCOUNT_TYPE + " FROM "
2232f251c778c06d21ed7693a70f4a1268ff929242eRoboErik            + Tables.CALENDARS + " WHERE " + Calendars._ID + "=new." + Events.CALENDAR_ID
224c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert            + ") AND " + Colors.COLOR_KEY + "=" + "new." + Events.EVENT_COLOR_KEY + " AND "
225c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert            + Colors.COLOR_TYPE + "=" + Colors.TYPE_EVENT + ") "
2262f251c778c06d21ed7693a70f4a1268ff929242eRoboErik            + " WHERE " + Events._ID + "=" + "old." + Events._ID + ";";
2272f251c778c06d21ed7693a70f4a1268ff929242eRoboErik    private static final String EVENT_COLOR_UPDATE_TRIGGER_NAME = "event_color_update";
2282f251c778c06d21ed7693a70f4a1268ff929242eRoboErik    private static final String CREATE_EVENT_COLOR_UPDATE_TRIGGER = "CREATE TRIGGER "
229387535fec9f646e0b7acb82d5354f2b5ebee4395RoboErik            + EVENT_COLOR_UPDATE_TRIGGER_NAME + " UPDATE OF " + Events.EVENT_COLOR_KEY + " ON "
230387535fec9f646e0b7acb82d5354f2b5ebee4395RoboErik            + Tables.EVENTS + " WHEN new." + Events.EVENT_COLOR_KEY + " NOT NULL BEGIN "
2312f251c778c06d21ed7693a70f4a1268ff929242eRoboErik            + EVENT_UPDATE_COLOR_TRIGGER_SQL + " END";
2322f251c778c06d21ed7693a70f4a1268ff929242eRoboErik
233935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden    /** Selects rows from Attendees for which the event_id refers to a nonexistent Event */
234935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden    private static final String WHERE_ATTENDEES_ORPHANS =
235935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            Attendees.EVENT_ID + " IN (SELECT " + Attendees.EVENT_ID + " FROM " +
236935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            Tables.ATTENDEES + " LEFT OUTER JOIN " + Tables.EVENTS + " ON " +
237935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            Attendees.EVENT_ID + "=" + Tables.EVENTS + "." + Events._ID +
238935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            " WHERE " + Tables.EVENTS + "." + Events._ID + " IS NULL)";
239935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden    /** Selects rows from Reminders for which the event_id refers to a nonexistent Event */
240935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden    private static final String WHERE_REMINDERS_ORPHANS =
241935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            Reminders.EVENT_ID + " IN (SELECT " + Reminders.EVENT_ID + " FROM " +
242935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            Tables.REMINDERS + " LEFT OUTER JOIN " + Tables.EVENTS + " ON " +
243935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            Reminders.EVENT_ID + "=" + Tables.EVENTS + "." + Events._ID +
244935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            " WHERE " + Tables.EVENTS + "." + Events._ID + " IS NULL)";
245935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden
2461b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio    private static final String SCHEMA_HTTPS = "https://";
2471b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio    private static final String SCHEMA_HTTP = "http://";
2481b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio
2499f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private final SyncStateContentProviderHelper mSyncState;
2509f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
2519f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private static CalendarDatabaseHelper sSingleton = null;
2529f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
2539f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private DatabaseUtils.InsertHelper mCalendarsInserter;
2542f251c778c06d21ed7693a70f4a1268ff929242eRoboErik    private DatabaseUtils.InsertHelper mColorsInserter;
2559f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private DatabaseUtils.InsertHelper mEventsInserter;
2569f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private DatabaseUtils.InsertHelper mEventsRawTimesInserter;
2579f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private DatabaseUtils.InsertHelper mInstancesInserter;
2589f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private DatabaseUtils.InsertHelper mAttendeesInserter;
2599f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private DatabaseUtils.InsertHelper mRemindersInserter;
2609f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private DatabaseUtils.InsertHelper mCalendarAlertsInserter;
2619f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private DatabaseUtils.InsertHelper mExtendedPropertiesInserter;
2629f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
2639f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    public long calendarsInsert(ContentValues values) {
2649f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        return mCalendarsInserter.insert(values);
2659f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
2669f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
2672f251c778c06d21ed7693a70f4a1268ff929242eRoboErik    public long colorsInsert(ContentValues values) {
2682f251c778c06d21ed7693a70f4a1268ff929242eRoboErik        return mColorsInserter.insert(values);
2692f251c778c06d21ed7693a70f4a1268ff929242eRoboErik    }
2702f251c778c06d21ed7693a70f4a1268ff929242eRoboErik
2719f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    public long eventsInsert(ContentValues values) {
2729f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        return mEventsInserter.insert(values);
2739f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
2749f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
2759f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    public long eventsRawTimesInsert(ContentValues values) {
2769f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        return mEventsRawTimesInserter.insert(values);
2779f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
2789f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
2799f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    public long eventsRawTimesReplace(ContentValues values) {
2809f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        return mEventsRawTimesInserter.replace(values);
2819f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
2829f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
2839f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    public long instancesInsert(ContentValues values) {
2849f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        return mInstancesInserter.insert(values);
2859f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
2869f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
287c874ed5c6cc0fcc6ac06ae7d20db0eab7d749608Ken Shirriff    public long instancesReplace(ContentValues values) {
288c874ed5c6cc0fcc6ac06ae7d20db0eab7d749608Ken Shirriff        return mInstancesInserter.replace(values);
289c874ed5c6cc0fcc6ac06ae7d20db0eab7d749608Ken Shirriff    }
290c874ed5c6cc0fcc6ac06ae7d20db0eab7d749608Ken Shirriff
2919f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    public long attendeesInsert(ContentValues values) {
2929f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        return mAttendeesInserter.insert(values);
2939f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
2949f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
2959f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    public long remindersInsert(ContentValues values) {
2969f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        return mRemindersInserter.insert(values);
2979f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
2989f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
2999f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    public long calendarAlertsInsert(ContentValues values) {
3009f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        return mCalendarAlertsInserter.insert(values);
3019f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
3029f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
3039f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    public long extendedPropertiesInsert(ContentValues values) {
3049f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        return mExtendedPropertiesInserter.insert(values);
3059f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
3069f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
3079f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    public static synchronized CalendarDatabaseHelper getInstance(Context context) {
3089f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        if (sSingleton == null) {
3099f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            sSingleton = new CalendarDatabaseHelper(context);
3109f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
3119f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        return sSingleton;
3129f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
3139f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
3149f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    /**
3159f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * Private constructor, callers except unit tests should obtain an instance through
3169f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * {@link #getInstance(android.content.Context)} instead.
3179f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     */
3187e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff    /* package */ CalendarDatabaseHelper(Context context) {
3199f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        super(context, DATABASE_NAME, null, DATABASE_VERSION);
32081d904d66bd746c077cc0baa6cf1f51fe030eac4Mason Tang        if (LOGD) Log.d(TAG, "Creating OpenHelper");
3219f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
3229f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        mSyncState = new SyncStateContentProviderHelper();
3239f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
3249f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
3259f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    @Override
3269f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    public void onOpen(SQLiteDatabase db) {
3279f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        mSyncState.onDatabaseOpened(db);
3289f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
3297cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio        mCalendarsInserter = new DatabaseUtils.InsertHelper(db, Tables.CALENDARS);
3302f251c778c06d21ed7693a70f4a1268ff929242eRoboErik        mColorsInserter = new DatabaseUtils.InsertHelper(db, Tables.COLORS);
3317cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio        mEventsInserter = new DatabaseUtils.InsertHelper(db, Tables.EVENTS);
3327cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio        mEventsRawTimesInserter = new DatabaseUtils.InsertHelper(db, Tables.EVENTS_RAW_TIMES);
3337cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio        mInstancesInserter = new DatabaseUtils.InsertHelper(db, Tables.INSTANCES);
3347cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio        mAttendeesInserter = new DatabaseUtils.InsertHelper(db, Tables.ATTENDEES);
3357cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio        mRemindersInserter = new DatabaseUtils.InsertHelper(db, Tables.REMINDERS);
3367cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio        mCalendarAlertsInserter = new DatabaseUtils.InsertHelper(db, Tables.CALENDAR_ALERTS);
3379f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        mExtendedPropertiesInserter =
3387cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                new DatabaseUtils.InsertHelper(db, Tables.EXTENDED_PROPERTIES);
3399f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
3409f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
341d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff    /*
342d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff     * Upgrade sync state table if necessary.  Note that the data bundle
343d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff     * in the table is not upgraded.
344d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff     *
345d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff     * The sync state used to be stored with version 3, but now uses the
346d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff     * same sync state code as contacts, which is version 1.  This code
347d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff     * upgrades from 3 to 1 if necessary.  (Yes, the numbers are unfortunately
348d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff     * backwards.)
349d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff     *
350d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff     * This code is only called when upgrading from an old calendar version,
351d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff     * so there is no problem if sync state version 3 gets used again in the
352d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff     * future.
353d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff     */
354d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff    private void upgradeSyncState(SQLiteDatabase db) {
355d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff        long version = DatabaseUtils.longForQuery(db,
356d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff                 "SELECT " + SYNC_STATE_META_VERSION_COLUMN
3577cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                 + " FROM " + Tables.SYNC_STATE_META,
358d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff                 null);
359d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff        if (version == PRE_FROYO_SYNC_STATE_VERSION) {
360d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff            Log.i(TAG, "Upgrading calendar sync state table");
361d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff            db.execSQL("CREATE TEMPORARY TABLE state_backup(_sync_account TEXT, "
362d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff                    + "_sync_account_type TEXT, data TEXT);");
363d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff            db.execSQL("INSERT INTO state_backup SELECT _sync_account, _sync_account_type, data"
364d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff                    + " FROM "
3657cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                    + Tables.SYNC_STATE
366d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff                    + " WHERE _sync_account is not NULL and _sync_account_type is not NULL;");
3677cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio            db.execSQL("DROP TABLE " + Tables.SYNC_STATE + ";");
368d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff            mSyncState.onDatabaseOpened(db);
3697cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio            db.execSQL("INSERT INTO " + Tables.SYNC_STATE + "("
370d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff                    + SyncStateContract.Columns.ACCOUNT_NAME + ","
371d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff                    + SyncStateContract.Columns.ACCOUNT_TYPE + ","
372d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff                    + SyncStateContract.Columns.DATA
373d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff                    + ") SELECT _sync_account, _sync_account_type, data from state_backup;");
374d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff            db.execSQL("DROP TABLE state_backup;");
375d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff        } else {
376d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff            // Wrong version to upgrade.
377d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff            // Don't need to do anything more here because mSyncState.onDatabaseOpened() will blow
378d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff            // away and recreate  the database (which will result in a resync).
379d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff            Log.w(TAG, "upgradeSyncState: current version is " + version + ", skipping upgrade.");
380d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff        }
381d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff    }
382d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff
3839f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    @Override
3849f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    public void onCreate(SQLiteDatabase db) {
385a6357118c223d00ed722ecd40ecdda92d705d211Erik        bootstrapDB(db);
386a6357118c223d00ed722ecd40ecdda92d705d211Erik    }
387a6357118c223d00ed722ecd40ecdda92d705d211Erik
388a6357118c223d00ed722ecd40ecdda92d705d211Erik    private void bootstrapDB(SQLiteDatabase db) {
3899f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        Log.i(TAG, "Bootstrapping database");
3909f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
3919f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        mSyncState.createDatabase(db);
3929f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
3932f251c778c06d21ed7693a70f4a1268ff929242eRoboErik        createColorsTable(db);
3942f251c778c06d21ed7693a70f4a1268ff929242eRoboErik
3951b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio        createCalendarsTable(db);
3969f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
397c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik        createEventsTable(db);
3989f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
3997cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio        db.execSQL("CREATE TABLE " + Tables.EVENTS_RAW_TIMES + " (" +
400b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.EventsRawTimes._ID + " INTEGER PRIMARY KEY," +
401b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.EventsRawTimes.EVENT_ID + " INTEGER NOT NULL," +
402b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.EventsRawTimes.DTSTART_2445 + " TEXT," +
403b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.EventsRawTimes.DTEND_2445 + " TEXT," +
404b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.EventsRawTimes.ORIGINAL_INSTANCE_TIME_2445 + " TEXT," +
405b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.EventsRawTimes.LAST_DATE_2445 + " TEXT," +
406b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                "UNIQUE (" + CalendarContract.EventsRawTimes.EVENT_ID + ")" +
4079f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                ");");
4089f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
4097cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio        db.execSQL("CREATE TABLE " + Tables.INSTANCES + " (" +
410b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Instances._ID + " INTEGER PRIMARY KEY," +
411b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Instances.EVENT_ID + " INTEGER," +
412b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Instances.BEGIN + " INTEGER," +         // UTC millis
413b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Instances.END + " INTEGER," +           // UTC millis
414b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Instances.START_DAY + " INTEGER," +      // Julian start day
415b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Instances.END_DAY + " INTEGER," +        // Julian end day
416b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Instances.START_MINUTE + " INTEGER," +   // minutes from midnight
417b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Instances.END_MINUTE + " INTEGER," +     // minutes from midnight
4187cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                "UNIQUE (" +
419b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                    CalendarContract.Instances.EVENT_ID + ", " +
420b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                    CalendarContract.Instances.BEGIN + ", " +
421b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                    CalendarContract.Instances.END + ")" +
4229f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                ");");
4239f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
4247cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio        db.execSQL("CREATE INDEX instancesStartDayIndex ON " + Tables.INSTANCES + " (" +
425b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Instances.START_DAY +
4269f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                ");");
4279f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
4281599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio        createCalendarMetaDataTable(db);
4299f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
430315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        createCalendarCacheTable(db, null);
431ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio
4327cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio        db.execSQL("CREATE TABLE " + Tables.ATTENDEES + " (" +
433b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Attendees._ID + " INTEGER PRIMARY KEY," +
434b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Attendees.EVENT_ID + " INTEGER," +
435b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Attendees.ATTENDEE_NAME + " TEXT," +
436b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Attendees.ATTENDEE_EMAIL + " TEXT," +
437b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Attendees.ATTENDEE_STATUS + " INTEGER," +
438b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Attendees.ATTENDEE_RELATIONSHIP + " INTEGER," +
439bafe9de156292f65b1079dd1eb586669f573d9e6Michael Chan                CalendarContract.Attendees.ATTENDEE_TYPE + " INTEGER," +
440bafe9de156292f65b1079dd1eb586669f573d9e6Michael Chan                CalendarContract.Attendees.ATTENDEE_IDENTITY + " TEXT," +
441bafe9de156292f65b1079dd1eb586669f573d9e6Michael Chan                CalendarContract.Attendees.ATTENDEE_ID_NAMESPACE + " TEXT" +
4429f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                ");");
4439f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
4447cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio        db.execSQL("CREATE INDEX attendeesEventIdIndex ON " + Tables.ATTENDEES + " (" +
445b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Attendees.EVENT_ID +
4469f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                ");");
4479f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
4487cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio        db.execSQL("CREATE TABLE " + Tables.REMINDERS + " (" +
449b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Reminders._ID + " INTEGER PRIMARY KEY," +
450b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Reminders.EVENT_ID + " INTEGER," +
451b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Reminders.MINUTES + " INTEGER," +
452b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Reminders.METHOD + " INTEGER NOT NULL" +
453b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                " DEFAULT " + CalendarContract.Reminders.METHOD_DEFAULT +
4549f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                ");");
4559f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
4567cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio        db.execSQL("CREATE INDEX remindersEventIdIndex ON " + Tables.REMINDERS + " (" +
457b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Reminders.EVENT_ID +
4589f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                ");");
4599f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
4607e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff         // This table stores the Calendar notifications that have gone off.
4617cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio        db.execSQL("CREATE TABLE " + Tables.CALENDAR_ALERTS + " (" +
462b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.CalendarAlerts._ID + " INTEGER PRIMARY KEY," +
463b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.CalendarAlerts.EVENT_ID + " INTEGER," +
464b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.CalendarAlerts.BEGIN + " INTEGER NOT NULL," +      // UTC millis
465b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.CalendarAlerts.END + " INTEGER NOT NULL," +        // UTC millis
466b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.CalendarAlerts.ALARM_TIME + " INTEGER NOT NULL," + // UTC millis
467d5f4742d7ba16d791edd9fd33a1a2a42eeac709bRoboErik                // UTC millis
468b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.CalendarAlerts.CREATION_TIME + " INTEGER NOT NULL DEFAULT 0," +
469d5f4742d7ba16d791edd9fd33a1a2a42eeac709bRoboErik                // UTC millis
470b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.CalendarAlerts.RECEIVED_TIME + " INTEGER NOT NULL DEFAULT 0," +
471d5f4742d7ba16d791edd9fd33a1a2a42eeac709bRoboErik                // UTC millis
472b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.CalendarAlerts.NOTIFY_TIME + " INTEGER NOT NULL DEFAULT 0," +
473b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.CalendarAlerts.STATE + " INTEGER NOT NULL," +
474b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.CalendarAlerts.MINUTES + " INTEGER," +
4757cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                "UNIQUE (" +
476b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                    CalendarContract.CalendarAlerts.ALARM_TIME + ", " +
477b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                    CalendarContract.CalendarAlerts.BEGIN + ", " +
478b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                    CalendarContract.CalendarAlerts.EVENT_ID + ")" +
4799f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                ");");
4809f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
4817cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio        db.execSQL("CREATE INDEX calendarAlertsEventIdIndex ON " + Tables.CALENDAR_ALERTS + " (" +
482b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.CalendarAlerts.EVENT_ID +
4839f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                ");");
4849f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
4857cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio        db.execSQL("CREATE TABLE " + Tables.EXTENDED_PROPERTIES + " (" +
486b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.ExtendedProperties._ID + " INTEGER PRIMARY KEY," +
487b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.ExtendedProperties.EVENT_ID + " INTEGER," +
488b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.ExtendedProperties.NAME + " TEXT," +
489b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.ExtendedProperties.VALUE + " TEXT" +
4909f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                ");");
4919f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
4927cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio        db.execSQL("CREATE INDEX extendedPropertiesEventIdIndex ON " + Tables.EXTENDED_PROPERTIES
4937cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                + " (" +
494b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.ExtendedProperties.EVENT_ID +
4959f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                ");");
4969f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
4977cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio        createEventsView(db);
4987cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio
4999f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        // Trigger to remove data tied to an event when we delete that event.
5007cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio        db.execSQL("CREATE TRIGGER events_cleanup_delete DELETE ON " + Tables.EVENTS + " " +
5019f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                "BEGIN " +
5027cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                EVENTS_CLEANUP_TRIGGER_SQL +
5039f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff                "END");
5049f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
5052f251c778c06d21ed7693a70f4a1268ff929242eRoboErik        // Triggers to update the color stored in an event or a calendar when
5062f251c778c06d21ed7693a70f4a1268ff929242eRoboErik        // the color_index is changed.
5072f251c778c06d21ed7693a70f4a1268ff929242eRoboErik        createColorsTriggers(db);
5082f251c778c06d21ed7693a70f4a1268ff929242eRoboErik
50934c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik        // Trigger to update exceptions when an original event updates its
51034c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik        // _sync_id
51134c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik        db.execSQL(CREATE_SYNC_ID_UPDATE_TRIGGER);
51234c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik
513470aa5bc291ca33d51dda356f38ac2954026da9aAlon Albert        scheduleSync(null /* all accounts */, false, null);
5149f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
5159f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
516c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik    private void createEventsTable(SQLiteDatabase db) {
517bcba82631ab0ee16efe58f0e0b0b9c18d93a6fd2Andy McFadden        // IMPORTANT: when adding new columns, be sure to update ALLOWED_IN_EXCEPTION and
518bcba82631ab0ee16efe58f0e0b0b9c18d93a6fd2Andy McFadden        // DONT_CLONE_INTO_EXCEPTION in CalendarProvider2.
519bcba82631ab0ee16efe58f0e0b0b9c18d93a6fd2Andy McFadden        //
520c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik        // TODO: do we need both dtend and duration?
52102f97c538fc46a08d857d2c807c76fd0eec12493RoboErik        // **When updating this be sure to also update LAST_SYNCED_EVENT_COLUMNS
522c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik        db.execSQL("CREATE TABLE " + Tables.EVENTS + " (" +
523935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden                CalendarContract.Events._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
524b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events._SYNC_ID + " TEXT," +
525b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.DIRTY + " INTEGER," +
5267a2531a4b68e9efe14353cc7f4a64a8c5613e5d3Alon Albert                CalendarContract.Events.MUTATORS + " TEXT," +
527b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.LAST_SYNCED + " INTEGER DEFAULT 0," +
528b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.CALENDAR_ID + " INTEGER NOT NULL," +
529b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.TITLE + " TEXT," +
530b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.EVENT_LOCATION + " TEXT," +
531b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.DESCRIPTION + " TEXT," +
532b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.EVENT_COLOR + " INTEGER," +
533387535fec9f646e0b7acb82d5354f2b5ebee4395RoboErik                CalendarContract.Events.EVENT_COLOR_KEY + " TEXT," +
534b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.STATUS + " INTEGER," +
535b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.SELF_ATTENDEE_STATUS + " INTEGER NOT NULL DEFAULT 0," +
536c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                // dtstart in millis since epoch
537b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.DTSTART + " INTEGER," +
538c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                // dtend in millis since epoch
539b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.DTEND + " INTEGER," +
540c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                // timezone for event
541b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.EVENT_TIMEZONE + " TEXT," +
542b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.DURATION + " TEXT," +
543b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.ALL_DAY + " INTEGER NOT NULL DEFAULT 0," +
544b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.ACCESS_LEVEL + " INTEGER NOT NULL DEFAULT 0," +
545b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.AVAILABILITY + " INTEGER NOT NULL DEFAULT 0," +
546b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.HAS_ALARM + " INTEGER NOT NULL DEFAULT 0," +
547b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.HAS_EXTENDED_PROPERTIES + " INTEGER NOT NULL DEFAULT 0," +
548b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.RRULE + " TEXT," +
549b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.RDATE + " TEXT," +
550b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.EXRULE + " TEXT," +
551b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.EXDATE + " TEXT," +
552b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.ORIGINAL_ID + " INTEGER," +
55334c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik                // ORIGINAL_SYNC_ID is the _sync_id of recurring event
554b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.ORIGINAL_SYNC_ID + " TEXT," +
55534c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik                // originalInstanceTime is in millis since epoch
556b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.ORIGINAL_INSTANCE_TIME + " INTEGER," +
557b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.ORIGINAL_ALL_DAY + " INTEGER," +
55834c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik                // lastDate is in millis since epoch
559b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.LAST_DATE + " INTEGER," +
560b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.HAS_ATTENDEE_DATA + " INTEGER NOT NULL DEFAULT 0," +
561b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.GUESTS_CAN_MODIFY + " INTEGER NOT NULL DEFAULT 0," +
562b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.GUESTS_CAN_INVITE_OTHERS + " INTEGER NOT NULL DEFAULT 1," +
563b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.GUESTS_CAN_SEE_GUESTS + " INTEGER NOT NULL DEFAULT 1," +
564b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.ORGANIZER + " STRING," +
565b2695bf3cfb173c4c5ba7bfd3c93ba8a51d65810Alon Albert                CalendarContract.Events.IS_ORGANIZER + " INTEGER," +
566b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.DELETED + " INTEGER NOT NULL DEFAULT 0," +
56734c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik                // timezone for event with allDay events are in local timezone
568b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.EVENT_END_TIMEZONE + " TEXT," +
569c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan                CalendarContract.Events.CUSTOM_APP_PACKAGE + " TEXT," +
570c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan                CalendarContract.Events.CUSTOM_APP_URI + " TEXT," +
571501e60bcb1b519d80723f7b64ba60bd079b8ec8dSara Ting                CalendarContract.Events.UID_2445 + " TEXT," +
57202f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                // SYNC_DATAX columns are available for use by sync adapters
573b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.SYNC_DATA1 + " TEXT," +
574b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.SYNC_DATA2 + " TEXT," +
575b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.SYNC_DATA3 + " TEXT," +
576b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.SYNC_DATA4 + " TEXT," +
577b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.SYNC_DATA5 + " TEXT," +
578b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.SYNC_DATA6 + " TEXT," +
579b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.SYNC_DATA7 + " TEXT," +
580b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.SYNC_DATA8 + " TEXT," +
581b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.SYNC_DATA9 + " TEXT," +
582b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.Events.SYNC_DATA10 + " TEXT" + ");");
58302f97c538fc46a08d857d2c807c76fd0eec12493RoboErik
58402f97c538fc46a08d857d2c807c76fd0eec12493RoboErik        // **When updating this be sure to also update LAST_SYNCED_EVENT_COLUMNS
58534c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik
58634c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik        db.execSQL("CREATE INDEX eventsCalendarIdIndex ON " + Tables.EVENTS + " ("
587b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Events.CALENDAR_ID + ");");
58834c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik    }
58934c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik
5902f251c778c06d21ed7693a70f4a1268ff929242eRoboErik    private void createEventsTable307(SQLiteDatabase db) {
5912f251c778c06d21ed7693a70f4a1268ff929242eRoboErik        db.execSQL("CREATE TABLE Events ("
5922f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "_id INTEGER PRIMARY KEY AUTOINCREMENT,"
5932f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "_sync_id TEXT,"
5942f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "dirty INTEGER,"
5952f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "lastSynced INTEGER DEFAULT 0,"
5962f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "calendar_id INTEGER NOT NULL,"
5972f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "title TEXT,"
5982f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "eventLocation TEXT,"
5992f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "description TEXT,"
6002f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "eventColor INTEGER,"
6012f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "eventStatus INTEGER,"
6022f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "selfAttendeeStatus INTEGER NOT NULL DEFAULT 0,"
6032f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                // dtstart in millis since epoch
6042f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "dtstart INTEGER,"
6052f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                // dtend in millis since epoch
6062f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "dtend INTEGER,"
6072f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                // timezone for event
6082f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "eventTimezone TEXT,"
6092f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "duration TEXT,"
6102f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "allDay INTEGER NOT NULL DEFAULT 0,"
6112f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "accessLevel INTEGER NOT NULL DEFAULT 0,"
6122f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "availability INTEGER NOT NULL DEFAULT 0,"
6132f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "hasAlarm INTEGER NOT NULL DEFAULT 0,"
6142f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "hasExtendedProperties INTEGER NOT NULL DEFAULT 0,"
6152f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "rrule TEXT,"
6162f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "rdate TEXT,"
6172f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "exrule TEXT,"
6182f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "exdate TEXT,"
6192f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "original_id INTEGER,"
6202f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                // ORIGINAL_SYNC_ID is the _sync_id of recurring event
6212f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "original_sync_id TEXT,"
6222f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                // originalInstanceTime is in millis since epoch
6232f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "originalInstanceTime INTEGER,"
6242f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "originalAllDay INTEGER,"
6252f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                // lastDate is in millis since epoch
6262f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "lastDate INTEGER,"
6272f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "hasAttendeeData INTEGER NOT NULL DEFAULT 0,"
6282f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "guestsCanModify INTEGER NOT NULL DEFAULT 0,"
6292f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "guestsCanInviteOthers INTEGER NOT NULL DEFAULT 1,"
6302f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "guestsCanSeeGuests INTEGER NOT NULL DEFAULT 1,"
6312f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "organizer STRING,"
6322f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "deleted INTEGER NOT NULL DEFAULT 0,"
6332f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                // timezone for event with allDay events are in local timezone
6342f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "eventEndTimezone TEXT,"
6352f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                // SYNC_DATAX columns are available for use by sync adapters
6362f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "sync_data1 TEXT,"
6372f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "sync_data2 TEXT,"
6382f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "sync_data3 TEXT,"
6392f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "sync_data4 TEXT,"
6402f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "sync_data5 TEXT,"
6412f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "sync_data6 TEXT,"
6422f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "sync_data7 TEXT,"
6432f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "sync_data8 TEXT,"
6442f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "sync_data9 TEXT,"
6452f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "sync_data10 TEXT);");
6462f251c778c06d21ed7693a70f4a1268ff929242eRoboErik
6472f251c778c06d21ed7693a70f4a1268ff929242eRoboErik        // **When updating this be sure to also update LAST_SYNCED_EVENT_COLUMNS
6482f251c778c06d21ed7693a70f4a1268ff929242eRoboErik
6492f251c778c06d21ed7693a70f4a1268ff929242eRoboErik        db.execSQL("CREATE INDEX eventsCalendarIdIndex ON Events (calendar_id);");
6502f251c778c06d21ed7693a70f4a1268ff929242eRoboErik    }
6512f251c778c06d21ed7693a70f4a1268ff929242eRoboErik
65234c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik    // TODO Remove this method after merging all ICS upgrades
65334c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik    private void createEventsTable300(SQLiteDatabase db) {
65402f97c538fc46a08d857d2c807c76fd0eec12493RoboErik        db.execSQL("CREATE TABLE Events (" +
65502f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "_id INTEGER PRIMARY KEY," +
65602f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "_sync_id TEXT," +
65702f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "_sync_version TEXT," +
65834c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik                // sync time in UTC
65902f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "_sync_time TEXT,"  +
66002f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "_sync_local_id INTEGER," +
66102f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "dirty INTEGER," +
66234c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik                // sync mark to filter out new rows
66302f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "_sync_mark INTEGER," +
66402f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "calendar_id INTEGER NOT NULL," +
66502f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "htmlUri TEXT," +
66602f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "title TEXT," +
66702f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "eventLocation TEXT," +
66802f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "description TEXT," +
66902f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "eventStatus INTEGER," +
67002f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "selfAttendeeStatus INTEGER NOT NULL DEFAULT 0," +
67102f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "commentsUri TEXT," +
67234c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik                // dtstart in millis since epoch
67302f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "dtstart INTEGER," +
67434c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik                // dtend in millis since epoch
67502f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "dtend INTEGER," +
67634c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik                // timezone for event
67702f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "eventTimezone TEXT," +
67802f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "duration TEXT," +
67902f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "allDay INTEGER NOT NULL DEFAULT 0," +
68002f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "accessLevel INTEGER NOT NULL DEFAULT 0," +
68102f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "availability INTEGER NOT NULL DEFAULT 0," +
68202f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "hasAlarm INTEGER NOT NULL DEFAULT 0," +
68302f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "hasExtendedProperties INTEGER NOT NULL DEFAULT 0," +
68402f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "rrule TEXT," +
68502f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "rdate TEXT," +
68602f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "exrule TEXT," +
68702f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "exdate TEXT," +
688c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                // originalEvent is the _sync_id of recurring event
68902f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "original_sync_id TEXT," +
690c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                // originalInstanceTime is in millis since epoch
69102f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "originalInstanceTime INTEGER," +
69202f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "originalAllDay INTEGER," +
693c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                // lastDate is in millis since epoch
69402f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "lastDate INTEGER," +
69502f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "hasAttendeeData INTEGER NOT NULL DEFAULT 0," +
69602f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "guestsCanModify INTEGER NOT NULL DEFAULT 0," +
69702f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "guestsCanInviteOthers INTEGER NOT NULL DEFAULT 1," +
69802f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "guestsCanSeeGuests INTEGER NOT NULL DEFAULT 1," +
69902f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "organizer STRING," +
70002f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "deleted INTEGER NOT NULL DEFAULT 0," +
701c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                // timezone for event with allDay events are in local timezone
70202f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "eventEndTimezone TEXT," +
703c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                // syncAdapterData is available for use by sync adapters
70402f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "sync_data1 TEXT);");
705c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik
70602f97c538fc46a08d857d2c807c76fd0eec12493RoboErik        db.execSQL("CREATE INDEX eventsCalendarIdIndex ON Events (calendar_id);");
707c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik    }
708c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik
7099ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert    private void createCalendarsTable303(SQLiteDatabase db) {
7109ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert        db.execSQL("CREATE TABLE " + Tables.CALENDARS + " (" +
7119ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                "_id INTEGER PRIMARY KEY," +
7129ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                "account_name TEXT," +
7139ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                "account_type TEXT," +
7149ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                "_sync_id TEXT," +
7159ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                "_sync_version TEXT," +
7169ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                "_sync_time TEXT," +  // UTC
7179ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                "dirty INTEGER," +
7189ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                "name TEXT," +
7199ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                "displayName TEXT," +
7209ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                "calendar_color INTEGER," +
7219ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                "access_level INTEGER," +
7229ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                "visible INTEGER NOT NULL DEFAULT 1," +
7239ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                "sync_events INTEGER NOT NULL DEFAULT 0," +
7249ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                "calendar_location TEXT," +
7259ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                "calendar_timezone TEXT," +
7269ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                "ownerAccount TEXT, " +
7279ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                "canOrganizerRespond INTEGER NOT NULL DEFAULT 1," +
7289ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                "canModifyTimeZone INTEGER DEFAULT 1," +
7299ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                "maxReminders INTEGER DEFAULT 5," +
730bf986d8deeeed9566e0badeba89d4800533cbca6Andy McFadden                "allowedReminders TEXT DEFAULT '0,1'," +
7319ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                "deleted INTEGER NOT NULL DEFAULT 0," +
7329ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                "cal_sync1 TEXT," +
7339ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                "cal_sync2 TEXT," +
7349ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                "cal_sync3 TEXT," +
7359ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                "cal_sync4 TEXT," +
7369ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                "cal_sync5 TEXT," +
7379ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                "cal_sync6 TEXT" +
7389ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                ");");
7399ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert
7409ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert        // Trigger to remove a calendar's events when we delete the calendar
7419ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert        db.execSQL("CREATE TRIGGER calendar_cleanup DELETE ON " + Tables.CALENDARS + " " +
7429ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                "BEGIN " +
7439ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                CALENDAR_CLEANUP_TRIGGER_SQL +
7449ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                "END");
7459ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert    }
7469ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert
7472f251c778c06d21ed7693a70f4a1268ff929242eRoboErik    private void createColorsTable(SQLiteDatabase db) {
7482f251c778c06d21ed7693a70f4a1268ff929242eRoboErik
7492f251c778c06d21ed7693a70f4a1268ff929242eRoboErik        db.execSQL("CREATE TABLE " + Tables.COLORS + " (" +
7502f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                CalendarContract.Colors._ID + " INTEGER PRIMARY KEY," +
7512f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                CalendarContract.Colors.ACCOUNT_NAME + " TEXT NOT NULL," +
7522f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                CalendarContract.Colors.ACCOUNT_TYPE + " TEXT NOT NULL," +
7532f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                CalendarContract.Colors.DATA + " TEXT," +
7542f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                CalendarContract.Colors.COLOR_TYPE + " INTEGER NOT NULL," +
755387535fec9f646e0b7acb82d5354f2b5ebee4395RoboErik                CalendarContract.Colors.COLOR_KEY + " TEXT NOT NULL," +
7562f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                CalendarContract.Colors.COLOR + " INTEGER NOT NULL" +
7572f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                ");");
7582f251c778c06d21ed7693a70f4a1268ff929242eRoboErik    }
7592f251c778c06d21ed7693a70f4a1268ff929242eRoboErik
7602f251c778c06d21ed7693a70f4a1268ff929242eRoboErik    public void createColorsTriggers(SQLiteDatabase db) {
7612f251c778c06d21ed7693a70f4a1268ff929242eRoboErik        db.execSQL(CREATE_EVENT_COLOR_UPDATE_TRIGGER);
7622f251c778c06d21ed7693a70f4a1268ff929242eRoboErik        db.execSQL(CREATE_CALENDAR_COLOR_UPDATE_TRIGGER);
7632f251c778c06d21ed7693a70f4a1268ff929242eRoboErik    }
7642f251c778c06d21ed7693a70f4a1268ff929242eRoboErik
7651b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio    private void createCalendarsTable(SQLiteDatabase db) {
7661b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio        db.execSQL("CREATE TABLE " + Tables.CALENDARS + " (" +
767c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                Calendars._ID + " INTEGER PRIMARY KEY," +
768c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                Calendars.ACCOUNT_NAME + " TEXT," +
769c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                Calendars.ACCOUNT_TYPE + " TEXT," +
770c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                Calendars._SYNC_ID + " TEXT," +
771c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                Calendars.DIRTY + " INTEGER," +
7727a2531a4b68e9efe14353cc7f4a64a8c5613e5d3Alon Albert                Calendars.MUTATORS + " TEXT," +
773c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                Calendars.NAME + " TEXT," +
774c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                Calendars.CALENDAR_DISPLAY_NAME + " TEXT," +
775c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                Calendars.CALENDAR_COLOR + " INTEGER," +
776c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                Calendars.CALENDAR_COLOR_KEY + " TEXT," +
777c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                Calendars.CALENDAR_ACCESS_LEVEL + " INTEGER," +
778c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                Calendars.VISIBLE + " INTEGER NOT NULL DEFAULT 1," +
779c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                Calendars.SYNC_EVENTS + " INTEGER NOT NULL DEFAULT 0," +
780c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                Calendars.CALENDAR_LOCATION + " TEXT," +
781c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                Calendars.CALENDAR_TIME_ZONE + " TEXT," +
782c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                Calendars.OWNER_ACCOUNT + " TEXT, " +
783b2695bf3cfb173c4c5ba7bfd3c93ba8a51d65810Alon Albert                Calendars.IS_PRIMARY + " INTEGER, " +
784c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                Calendars.CAN_ORGANIZER_RESPOND + " INTEGER NOT NULL DEFAULT 1," +
785c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                Calendars.CAN_MODIFY_TIME_ZONE + " INTEGER DEFAULT 1," +
786c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                Calendars.CAN_PARTIALLY_UPDATE + " INTEGER DEFAULT 0," +
787c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                Calendars.MAX_REMINDERS + " INTEGER DEFAULT 5," +
788c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                Calendars.ALLOWED_REMINDERS + " TEXT DEFAULT '0,1'," +
789c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                Calendars.ALLOWED_AVAILABILITY + " TEXT DEFAULT '0,1'," +
790c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                Calendars.ALLOWED_ATTENDEE_TYPES + " TEXT DEFAULT '0,1,2'," +
791c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                Calendars.DELETED + " INTEGER NOT NULL DEFAULT 0," +
792c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                Calendars.CAL_SYNC1 + " TEXT," +
793c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                Calendars.CAL_SYNC2 + " TEXT," +
794c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                Calendars.CAL_SYNC3 + " TEXT," +
795c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                Calendars.CAL_SYNC4 + " TEXT," +
796c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                Calendars.CAL_SYNC5 + " TEXT," +
797c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                Calendars.CAL_SYNC6 + " TEXT," +
798c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                Calendars.CAL_SYNC7 + " TEXT," +
799c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                Calendars.CAL_SYNC8 + " TEXT," +
800c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                Calendars.CAL_SYNC9 + " TEXT," +
801c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                Calendars.CAL_SYNC10 + " TEXT" +
802fa332ecedc0c340109811552407142f6e4f600b2RoboErik                ");");
803fa332ecedc0c340109811552407142f6e4f600b2RoboErik
804fa332ecedc0c340109811552407142f6e4f600b2RoboErik        // Trigger to remove a calendar's events when we delete the calendar
805fa332ecedc0c340109811552407142f6e4f600b2RoboErik        db.execSQL("CREATE TRIGGER calendar_cleanup DELETE ON " + Tables.CALENDARS + " " +
806fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "BEGIN " +
807fa332ecedc0c340109811552407142f6e4f600b2RoboErik                CALENDAR_CLEANUP_TRIGGER_SQL +
808fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "END");
809fa332ecedc0c340109811552407142f6e4f600b2RoboErik    }
810fa332ecedc0c340109811552407142f6e4f600b2RoboErik
8112f251c778c06d21ed7693a70f4a1268ff929242eRoboErik    private void createCalendarsTable305(SQLiteDatabase db) {
8122f251c778c06d21ed7693a70f4a1268ff929242eRoboErik        db.execSQL("CREATE TABLE Calendars (" +
8132f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                "_id INTEGER PRIMARY KEY," +
8142f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                "account_name TEXT," +
8152f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                "account_type TEXT," +
8162f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                "_sync_id TEXT," +
8172f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                "dirty INTEGER," +
8182f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                "name TEXT," +
8192f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                "calendar_displayName TEXT," +
8202f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                "calendar_color INTEGER," +
8212f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                "calendar_access_level INTEGER," +
8222f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                "visible INTEGER NOT NULL DEFAULT 1," +
8232f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                "sync_events INTEGER NOT NULL DEFAULT 0," +
8242f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                "calendar_location TEXT," +
8252f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                "calendar_timezone TEXT," +
8262f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                "ownerAccount TEXT, " +
8272f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                "canOrganizerRespond INTEGER NOT NULL DEFAULT 1," +
8282f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                "canModifyTimeZone INTEGER DEFAULT 1," +
8292f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                "canPartiallyUpdate INTEGER DEFAULT 0," +
8302f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                "maxReminders INTEGER DEFAULT 5," +
8312f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                "allowedReminders TEXT DEFAULT '0,1'," +
8322f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                "deleted INTEGER NOT NULL DEFAULT 0," +
8332f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                "cal_sync1 TEXT," +
8342f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                "cal_sync2 TEXT," +
8352f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                "cal_sync3 TEXT," +
8362f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                "cal_sync4 TEXT," +
8372f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                "cal_sync5 TEXT," +
8382f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                "cal_sync6 TEXT," +
8392f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                "cal_sync7 TEXT," +
8402f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                "cal_sync8 TEXT," +
8412f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                "cal_sync9 TEXT," +
8422f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                "cal_sync10 TEXT" +
8432f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                ");");
8442f251c778c06d21ed7693a70f4a1268ff929242eRoboErik
8452f251c778c06d21ed7693a70f4a1268ff929242eRoboErik        // Trigger to remove a calendar's events when we delete the calendar
8462f251c778c06d21ed7693a70f4a1268ff929242eRoboErik        db.execSQL("CREATE TRIGGER calendar_cleanup DELETE ON Calendars " +
8472f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                "BEGIN " +
8482f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                "DELETE FROM Events WHERE calendar_id=old._id;" +
8492f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                "END");
8502f251c778c06d21ed7693a70f4a1268ff929242eRoboErik    }
8512f251c778c06d21ed7693a70f4a1268ff929242eRoboErik
852fa332ecedc0c340109811552407142f6e4f600b2RoboErik    private void createCalendarsTable300(SQLiteDatabase db) {
853fa332ecedc0c340109811552407142f6e4f600b2RoboErik        db.execSQL("CREATE TABLE " + Tables.CALENDARS + " (" +
854fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "_id INTEGER PRIMARY KEY," +
855fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "account_name TEXT," +
856fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "account_type TEXT," +
857fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "_sync_id TEXT," +
858fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "_sync_version TEXT," +
859fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "_sync_time TEXT," +  // UTC
860fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "dirty INTEGER," +
861fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "name TEXT," +
862fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "displayName TEXT," +
863fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "calendar_color INTEGER," +
864fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "access_level INTEGER," +
865fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "visible INTEGER NOT NULL DEFAULT 1," +
866fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "sync_events INTEGER NOT NULL DEFAULT 0," +
867fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "calendar_location TEXT," +
868fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "calendar_timezone TEXT," +
869fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "ownerAccount TEXT, " +
870fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "canOrganizerRespond INTEGER NOT NULL DEFAULT 1," +
871fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "canModifyTimeZone INTEGER DEFAULT 1," +
872fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "maxReminders INTEGER DEFAULT 5," +
873fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "allowedReminders TEXT DEFAULT '0,1,2'," +
874fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "deleted INTEGER NOT NULL DEFAULT 0," +
875fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "sync1 TEXT," +
876fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "sync2 TEXT," +
877fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "sync3 TEXT," +
878fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "sync4 TEXT," +
879fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "sync5 TEXT," +
880fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "sync6 TEXT" +
8811b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio                ");");
8821b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio
8831b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio        // Trigger to remove a calendar's events when we delete the calendar
8841b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio        db.execSQL("CREATE TRIGGER calendar_cleanup DELETE ON " + Tables.CALENDARS + " " +
8851b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio                "BEGIN " +
8861b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio                CALENDAR_CLEANUP_TRIGGER_SQL +
8871b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio                "END");
8881b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio    }
8891b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio
890c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik    private void createCalendarsTable205(SQLiteDatabase db) {
891c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik        db.execSQL("CREATE TABLE Calendars (" +
892c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "_id INTEGER PRIMARY KEY," +
893c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "_sync_account TEXT," +
894c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "_sync_account_type TEXT," +
895c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "_sync_id TEXT," +
896c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "_sync_version TEXT," +
897c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "_sync_time TEXT," +  // UTC
898c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "_sync_dirty INTEGER," +
899c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "name TEXT," +
900c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "displayName TEXT," +
901c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "color INTEGER," +
902c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "access_level INTEGER," +
903c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "visible INTEGER NOT NULL DEFAULT 1," +
904c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "sync_events INTEGER NOT NULL DEFAULT 0," +
905c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "location TEXT," +
906c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "timezone TEXT," +
907c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "ownerAccount TEXT, " +
908c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "canOrganizerRespond INTEGER NOT NULL DEFAULT 1," +
909c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "canModifyTimeZone INTEGER DEFAULT 1, " +
910c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "maxReminders INTEGER DEFAULT 5," +
911c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "deleted INTEGER NOT NULL DEFAULT 0," +
912c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "sync1 TEXT," +
913c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "sync2 TEXT," +
914c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "sync3 TEXT," +
915c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "sync4 TEXT," +
916c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "sync5 TEXT," +
917c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "sync6 TEXT" +
918c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                ");");
919c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik
920c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik        createCalendarsCleanup200(db);
921c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik    }
922c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik
923180076a810558478f55ade53ebef0a2ddfa6bbc0Andy McFadden    private void createCalendarsTable202(SQLiteDatabase db) {
9242cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("CREATE TABLE Calendars (" +
9252cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_id INTEGER PRIMARY KEY," +
9262cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_account TEXT," +
9272cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_account_type TEXT," +
9282cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_id TEXT," +
9292cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_version TEXT," +
9302cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_time TEXT," +  // UTC
9312cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_local_id INTEGER," +
9322cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_dirty INTEGER," +
9332cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_mark INTEGER," + // Used to filter out new rows
9342cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "name TEXT," +
9352cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "displayName TEXT," +
9362cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "color INTEGER," +
9372cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "access_level INTEGER," +
9382cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "selected INTEGER NOT NULL DEFAULT 1," +
9392cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "sync_events INTEGER NOT NULL DEFAULT 0," +
9402cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "location TEXT," +
9412cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "timezone TEXT," +
9422cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "ownerAccount TEXT, " +
9432cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "organizerCanRespond INTEGER NOT NULL DEFAULT 1," +
9442cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "deleted INTEGER NOT NULL DEFAULT 0," +
9452cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "sync1 TEXT," +
9462cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "sync2 TEXT," +
9472cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "sync3 TEXT," +
9482cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "sync4 TEXT," +
9492cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "sync5 TEXT" +
9502cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                ");");
9512cff10f1a005bd7302245d4c680cf851193c3a97RoboErik
9524067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden        createCalendarsCleanup200(db);
9532cff10f1a005bd7302245d4c680cf851193c3a97RoboErik    }
9542cff10f1a005bd7302245d4c680cf851193c3a97RoboErik
9552cff10f1a005bd7302245d4c680cf851193c3a97RoboErik    private void createCalendarsTable200(SQLiteDatabase db) {
9562cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("CREATE TABLE Calendars (" +
9572cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_id INTEGER PRIMARY KEY," +
9582cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_account TEXT," +
9592cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_account_type TEXT," +
9602cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_id TEXT," +
9612cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_version TEXT," +
9622cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_time TEXT," +  // UTC
9632cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_local_id INTEGER," +
9642cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_dirty INTEGER," +
9652cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_mark INTEGER," + // Used to filter out new rows
9662cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "name TEXT," +
9672cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "displayName TEXT," +
9682cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "hidden INTEGER NOT NULL DEFAULT 0," +
9692cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "color INTEGER," +
9702cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "access_level INTEGER," +
9712cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "selected INTEGER NOT NULL DEFAULT 1," +
9722cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "sync_events INTEGER NOT NULL DEFAULT 0," +
9732cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "location TEXT," +
9742cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "timezone TEXT," +
9752cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "ownerAccount TEXT, " +
9762cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "organizerCanRespond INTEGER NOT NULL DEFAULT 1," +
9772cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "deleted INTEGER NOT NULL DEFAULT 0," +
9782cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "sync1 TEXT," +
9792cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "sync2 TEXT," +
9802cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "sync3 TEXT" +
9812cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                ");");
9822cff10f1a005bd7302245d4c680cf851193c3a97RoboErik
9834067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden        createCalendarsCleanup200(db);
9844067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden    }
9854067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden
9864067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden    /** Trigger to remove a calendar's events when we delete the calendar */
9874067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden    private void createCalendarsCleanup200(SQLiteDatabase db) {
9882cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("CREATE TRIGGER calendar_cleanup DELETE ON Calendars " +
9892cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "BEGIN " +
9902cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "DELETE FROM Events WHERE calendar_id=old._id;" +
9912cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "END");
9922cff10f1a005bd7302245d4c680cf851193c3a97RoboErik    }
9932cff10f1a005bd7302245d4c680cf851193c3a97RoboErik
9941599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio    private void createCalendarMetaDataTable(SQLiteDatabase db) {
9957cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio        db.execSQL("CREATE TABLE " + Tables.CALENDAR_META_DATA + " (" +
996b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.CalendarMetaData._ID + " INTEGER PRIMARY KEY," +
997b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.CalendarMetaData.LOCAL_TIMEZONE + " TEXT," +
998b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.CalendarMetaData.MIN_INSTANCE + " INTEGER," +      // UTC millis
999b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                CalendarContract.CalendarMetaData.MAX_INSTANCE + " INTEGER" +       // UTC millis
10001599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio                ");");
10011599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio    }
10021599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio
10032cff10f1a005bd7302245d4c680cf851193c3a97RoboErik    private void createCalendarMetaDataTable59(SQLiteDatabase db) {
10042cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("CREATE TABLE CalendarMetaData (" +
10052cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_id INTEGER PRIMARY KEY," +
10062cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "localTimezone TEXT," +
10072cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "minInstance INTEGER," +      // UTC millis
10082cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "maxInstance INTEGER" +       // UTC millis
10092cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                ");");
10102cff10f1a005bd7302245d4c680cf851193c3a97RoboErik    }
10112cff10f1a005bd7302245d4c680cf851193c3a97RoboErik
1012315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio    private void createCalendarCacheTable(SQLiteDatabase db, String oldTimezoneDbVersion) {
1013754b6d0e96c7df4cb649a48cde21b72c3dcedf4aErik        // This is a hack because versioning skipped version number 61 of schema
1014754b6d0e96c7df4cb649a48cde21b72c3dcedf4aErik        // TODO after version 70 this can be removed
10157cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio        db.execSQL("DROP TABLE IF EXISTS " + Tables.CALENDAR_CACHE + ";");
1016754b6d0e96c7df4cb649a48cde21b72c3dcedf4aErik
1017754b6d0e96c7df4cb649a48cde21b72c3dcedf4aErik        // IF NOT EXISTS should be normal pattern for table creation
10187cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio        db.execSQL("CREATE TABLE IF NOT EXISTS " + Tables.CALENDAR_CACHE + " (" +
10197cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                CalendarCache.COLUMN_NAME_ID + " INTEGER PRIMARY KEY," +
10207cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                CalendarCache.COLUMN_NAME_KEY + " TEXT NOT NULL," +
10217cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                CalendarCache.COLUMN_NAME_VALUE + " TEXT" +
1022ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio                ");");
1023ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio
1024315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        initCalendarCacheTable(db, oldTimezoneDbVersion);
10252cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        updateCalendarCacheTable(db);
1026b492524403ca34b0cb03bfad6456909494479925Fabrice Di Meglio    }
1027b492524403ca34b0cb03bfad6456909494479925Fabrice Di Meglio
1028315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio    private void initCalendarCacheTable(SQLiteDatabase db, String oldTimezoneDbVersion) {
1029315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        String timezoneDbVersion = (oldTimezoneDbVersion != null) ?
1030315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio                oldTimezoneDbVersion : CalendarCache.DEFAULT_TIMEZONE_DATABASE_VERSION;
1031315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio
1032315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        // Set the default timezone database version
1033258fc0a0054d6aba8556921c270379cea6bf3de1Fabrice Di Meglio        db.execSQL("INSERT OR REPLACE INTO " + Tables.CALENDAR_CACHE +
1034258fc0a0054d6aba8556921c270379cea6bf3de1Fabrice Di Meglio                " (" + CalendarCache.COLUMN_NAME_ID + ", " +
1035258fc0a0054d6aba8556921c270379cea6bf3de1Fabrice Di Meglio                CalendarCache.COLUMN_NAME_KEY + ", " +
1036258fc0a0054d6aba8556921c270379cea6bf3de1Fabrice Di Meglio                CalendarCache.COLUMN_NAME_VALUE + ") VALUES (" +
1037b492524403ca34b0cb03bfad6456909494479925Fabrice Di Meglio                CalendarCache.KEY_TIMEZONE_DATABASE_VERSION.hashCode() + "," +
1038470aa5bc291ca33d51dda356f38ac2954026da9aAlon Albert                "'" + CalendarCache.KEY_TIMEZONE_DATABASE_VERSION + "'," +
1039315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio                "'" + timezoneDbVersion + "'" +
1040315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio                ");");
1041315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio    }
1042315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio
10432cff10f1a005bd7302245d4c680cf851193c3a97RoboErik    private void updateCalendarCacheTable(SQLiteDatabase db) {
1044315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        // Define the default timezone type for Instances timezone management
1045258fc0a0054d6aba8556921c270379cea6bf3de1Fabrice Di Meglio        db.execSQL("INSERT INTO " + Tables.CALENDAR_CACHE +
1046258fc0a0054d6aba8556921c270379cea6bf3de1Fabrice Di Meglio                " (" + CalendarCache.COLUMN_NAME_ID + ", " +
1047258fc0a0054d6aba8556921c270379cea6bf3de1Fabrice Di Meglio                CalendarCache.COLUMN_NAME_KEY + ", " +
1048258fc0a0054d6aba8556921c270379cea6bf3de1Fabrice Di Meglio                CalendarCache.COLUMN_NAME_VALUE + ") VALUES (" +
1049315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio                CalendarCache.KEY_TIMEZONE_TYPE.hashCode() + "," +
1050315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio                "'" + CalendarCache.KEY_TIMEZONE_TYPE + "',"  +
1051315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio                "'" + CalendarCache.TIMEZONE_TYPE_AUTO + "'" +
1052315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio                ");");
1053315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio
1054315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        String defaultTimezone = TimeZone.getDefault().getID();
1055315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio
1056315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        // Define the default timezone for Instances
1057258fc0a0054d6aba8556921c270379cea6bf3de1Fabrice Di Meglio        db.execSQL("INSERT INTO " + Tables.CALENDAR_CACHE +
1058258fc0a0054d6aba8556921c270379cea6bf3de1Fabrice Di Meglio                " (" + CalendarCache.COLUMN_NAME_ID + ", " +
1059258fc0a0054d6aba8556921c270379cea6bf3de1Fabrice Di Meglio                CalendarCache.COLUMN_NAME_KEY + ", " +
1060258fc0a0054d6aba8556921c270379cea6bf3de1Fabrice Di Meglio                CalendarCache.COLUMN_NAME_VALUE + ") VALUES (" +
1061315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio                CalendarCache.KEY_TIMEZONE_INSTANCES.hashCode() + "," +
1062315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio                "'" + CalendarCache.KEY_TIMEZONE_INSTANCES + "',"  +
1063315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio                "'" + defaultTimezone + "'" +
1064315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio                ");");
1065315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio
1066315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        // Define the default previous timezone for Instances
1067258fc0a0054d6aba8556921c270379cea6bf3de1Fabrice Di Meglio        db.execSQL("INSERT INTO " + Tables.CALENDAR_CACHE +
1068258fc0a0054d6aba8556921c270379cea6bf3de1Fabrice Di Meglio                " (" + CalendarCache.COLUMN_NAME_ID + ", " +
1069258fc0a0054d6aba8556921c270379cea6bf3de1Fabrice Di Meglio                CalendarCache.COLUMN_NAME_KEY + ", " +
1070258fc0a0054d6aba8556921c270379cea6bf3de1Fabrice Di Meglio                CalendarCache.COLUMN_NAME_VALUE + ") VALUES (" +
1071315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio                CalendarCache.KEY_TIMEZONE_INSTANCES_PREVIOUS.hashCode() + "," +
1072315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio                "'" + CalendarCache.KEY_TIMEZONE_INSTANCES_PREVIOUS + "',"  +
1073315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio                "'" + defaultTimezone + "'" +
1074ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio                ");");
1075ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio    }
1076ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio
10772cff10f1a005bd7302245d4c680cf851193c3a97RoboErik    private void initCalendarCacheTable203(SQLiteDatabase db, String oldTimezoneDbVersion) {
10782cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        String timezoneDbVersion = (oldTimezoneDbVersion != null) ?
10792cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                oldTimezoneDbVersion : "2009s";
10802cff10f1a005bd7302245d4c680cf851193c3a97RoboErik
10812cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        // Set the default timezone database version
10822cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("INSERT OR REPLACE INTO CalendarCache" +
10832cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                " (_id, " +
10842cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "key, " +
10852cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "value) VALUES (" +
10862cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "timezoneDatabaseVersion".hashCode() + "," +
10872cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "'timezoneDatabaseVersion',"  +
10882cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "'" + timezoneDbVersion + "'" +
10892cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                ");");
10902cff10f1a005bd7302245d4c680cf851193c3a97RoboErik    }
10912cff10f1a005bd7302245d4c680cf851193c3a97RoboErik
10922cff10f1a005bd7302245d4c680cf851193c3a97RoboErik    private void updateCalendarCacheTableTo203(SQLiteDatabase db) {
10932cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        // Define the default timezone type for Instances timezone management
10942cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("INSERT INTO CalendarCache" +
10952cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                " (_id, key, value) VALUES (" +
10962cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "timezoneType".hashCode() + "," +
10972cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "'timezoneType',"  +
10982cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "'auto'" +
10992cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                ");");
11002cff10f1a005bd7302245d4c680cf851193c3a97RoboErik
11012cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        String defaultTimezone = TimeZone.getDefault().getID();
11022cff10f1a005bd7302245d4c680cf851193c3a97RoboErik
11032cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        // Define the default timezone for Instances
11042cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("INSERT INTO CalendarCache" +
11052cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                " (_id, key, value) VALUES (" +
11062cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "timezoneInstances".hashCode() + "," +
11072cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "'timezoneInstances',"  +
11082cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "'" + defaultTimezone + "'" +
11092cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                ");");
11102cff10f1a005bd7302245d4c680cf851193c3a97RoboErik
11112cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        // Define the default previous timezone for Instances
11122cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("INSERT INTO CalendarCache" +
11132cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                " (_id, key, value) VALUES (" +
11142cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "timezoneInstancesPrevious".hashCode() + "," +
11152cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "'timezoneInstancesPrevious',"  +
11162cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "'" + defaultTimezone + "'" +
11172cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                ");");
11182cff10f1a005bd7302245d4c680cf851193c3a97RoboErik    }
11192cff10f1a005bd7302245d4c680cf851193c3a97RoboErik
1120935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden    /**
1121935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden     * Removes orphaned data from the database.  Specifically:
1122935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden     * <ul>
1123935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden     * <li>Attendees with an event_id for a nonexistent Event
1124935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden     * <li>Reminders with an event_id for a nonexistent Event
1125935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden     * </ul>
1126935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden     */
1127935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden    static void removeOrphans(SQLiteDatabase db) {
1128935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden        if (false) {        // debug mode
1129935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            String SELECT_ATTENDEES_ORPHANS = "SELECT " +
1130935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden                    Attendees._ID + ", " + Attendees.EVENT_ID + " FROM " + Tables.ATTENDEES +
1131935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden                    " WHERE " + WHERE_ATTENDEES_ORPHANS;
1132935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden
1133935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            Cursor cursor = null;
1134935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            try {
1135935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden                Log.i(TAG, "Attendees orphans:");
1136935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden                cursor = db.rawQuery(SELECT_ATTENDEES_ORPHANS, null);
1137935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden                DatabaseUtils.dumpCursor(cursor);
1138935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            } finally {
1139935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden                if (cursor != null) {
1140935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden                    cursor.close();
1141935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden                }
1142935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            }
1143935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden
1144935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            String SELECT_REMINDERS_ORPHANS = "SELECT " +
1145935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden                    Attendees._ID + ", " + Reminders.EVENT_ID + " FROM " + Tables.REMINDERS +
1146935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden                    " WHERE " + WHERE_REMINDERS_ORPHANS;
1147935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            cursor = null;
1148935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            try {
1149935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden                Log.i(TAG, "Reminders orphans:");
1150935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden                cursor = db.rawQuery(SELECT_REMINDERS_ORPHANS, null);
1151935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden                DatabaseUtils.dumpCursor(cursor);
1152935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            } finally {
1153935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden                if (cursor != null) {
1154935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden                    cursor.close();
1155935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden                }
1156935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            }
1157935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden
1158935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            return;
1159935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden        }
1160935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden
1161935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden        Log.d(TAG, "Checking for orphaned entries");
1162935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden        int count;
1163935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden
1164935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden        count = db.delete(Tables.ATTENDEES, WHERE_ATTENDEES_ORPHANS, null);
1165935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden        if (count != 0) {
1166935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            Log.i(TAG, "Deleted " + count + " orphaned Attendees");
1167935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden        }
1168935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden
1169935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden        count = db.delete(Tables.REMINDERS, WHERE_REMINDERS_ORPHANS, null);
1170935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden        if (count != 0) {
1171935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            Log.i(TAG, "Deleted " + count + " orphaned Reminders");
1172935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden        }
1173935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden    }
1174935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden
1175935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden
11769f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    @Override
11779f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
11787544af675ce2fd78f33198e5e9194f2bc7bd129fAndy McFadden        Log.i(TAG, "Upgrading DB from version " + oldVersion + " to " + newVersion);
11797544af675ce2fd78f33198e5e9194f2bc7bd129fAndy McFadden        long startWhen = System.nanoTime();
11807544af675ce2fd78f33198e5e9194f2bc7bd129fAndy McFadden
1181ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        if (oldVersion < 49) {
11829f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            dropTables(db);
11830d8699eedb0f3bcec1854b9753ae59154a122726Michael Chan            bootstrapDB(db);
11840d8699eedb0f3bcec1854b9753ae59154a122726Michael Chan            return;
11859f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
11869f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
11871599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio        // From schema versions 59 to version 66, the CalendarMetaData table definition had lost
11881599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio        // the primary key leading to having the CalendarMetaData with multiple rows instead of
11891599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio        // only one. The Instance table was then corrupted (during Instance expansion we are using
11901599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio        // the localTimezone, minInstance and maxInstance from CalendarMetaData table.
11911599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio        // This boolean helps us tracking the need to recreate the CalendarMetaData table and
11921599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio        // clear the Instance table (and thus force an Instance expansion).
1193679d544f38aa33d00c12884b987d8f8af2a6a6d3Fabrice Di Meglio        boolean recreateMetaDataAndInstances = (oldVersion >= 59 && oldVersion <= 66);
11942cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        boolean createEventsView = false;
11951599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio
1196a6357118c223d00ed722ecd40ecdda92d705d211Erik        try {
1197a6357118c223d00ed722ecd40ecdda92d705d211Erik            if (oldVersion < 51) {
1198a6357118c223d00ed722ecd40ecdda92d705d211Erik                upgradeToVersion51(db); // From 50 or 51
1199a6357118c223d00ed722ecd40ecdda92d705d211Erik                oldVersion = 51;
1200a6357118c223d00ed722ecd40ecdda92d705d211Erik            }
1201a6357118c223d00ed722ecd40ecdda92d705d211Erik            if (oldVersion == 51) {
1202a6357118c223d00ed722ecd40ecdda92d705d211Erik                upgradeToVersion52(db);
1203a6357118c223d00ed722ecd40ecdda92d705d211Erik                oldVersion += 1;
1204a6357118c223d00ed722ecd40ecdda92d705d211Erik            }
1205a6357118c223d00ed722ecd40ecdda92d705d211Erik            if (oldVersion == 52) {
1206a6357118c223d00ed722ecd40ecdda92d705d211Erik                upgradeToVersion53(db);
1207a6357118c223d00ed722ecd40ecdda92d705d211Erik                oldVersion += 1;
1208a6357118c223d00ed722ecd40ecdda92d705d211Erik            }
1209a6357118c223d00ed722ecd40ecdda92d705d211Erik            if (oldVersion == 53) {
1210a6357118c223d00ed722ecd40ecdda92d705d211Erik                upgradeToVersion54(db);
1211a6357118c223d00ed722ecd40ecdda92d705d211Erik                oldVersion += 1;
1212a6357118c223d00ed722ecd40ecdda92d705d211Erik            }
1213a6357118c223d00ed722ecd40ecdda92d705d211Erik            if (oldVersion == 54) {
1214a6357118c223d00ed722ecd40ecdda92d705d211Erik                upgradeToVersion55(db);
1215a6357118c223d00ed722ecd40ecdda92d705d211Erik                oldVersion += 1;
1216a6357118c223d00ed722ecd40ecdda92d705d211Erik            }
1217a6357118c223d00ed722ecd40ecdda92d705d211Erik            if (oldVersion == 55 || oldVersion == 56) {
1218a6357118c223d00ed722ecd40ecdda92d705d211Erik                // Both require resync, so just schedule it once
1219a6357118c223d00ed722ecd40ecdda92d705d211Erik                upgradeResync(db);
1220a6357118c223d00ed722ecd40ecdda92d705d211Erik            }
1221a6357118c223d00ed722ecd40ecdda92d705d211Erik            if (oldVersion == 55) {
1222a6357118c223d00ed722ecd40ecdda92d705d211Erik                upgradeToVersion56(db);
1223a6357118c223d00ed722ecd40ecdda92d705d211Erik                oldVersion += 1;
1224a6357118c223d00ed722ecd40ecdda92d705d211Erik            }
1225a6357118c223d00ed722ecd40ecdda92d705d211Erik            if (oldVersion == 56) {
1226a6357118c223d00ed722ecd40ecdda92d705d211Erik                upgradeToVersion57(db);
1227a6357118c223d00ed722ecd40ecdda92d705d211Erik                oldVersion += 1;
1228a6357118c223d00ed722ecd40ecdda92d705d211Erik            }
1229a6357118c223d00ed722ecd40ecdda92d705d211Erik            if (oldVersion == 57) {
1230a6357118c223d00ed722ecd40ecdda92d705d211Erik                // Changes are undone upgrading to 60, so don't do anything.
1231a6357118c223d00ed722ecd40ecdda92d705d211Erik                oldVersion += 1;
1232a6357118c223d00ed722ecd40ecdda92d705d211Erik            }
1233a6357118c223d00ed722ecd40ecdda92d705d211Erik            if (oldVersion == 58) {
1234a6357118c223d00ed722ecd40ecdda92d705d211Erik                upgradeToVersion59(db);
1235a6357118c223d00ed722ecd40ecdda92d705d211Erik                oldVersion += 1;
1236a6357118c223d00ed722ecd40ecdda92d705d211Erik            }
1237a6357118c223d00ed722ecd40ecdda92d705d211Erik            if (oldVersion == 59) {
1238a6357118c223d00ed722ecd40ecdda92d705d211Erik                upgradeToVersion60(db);
12392cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                createEventsView = true;
1240a6357118c223d00ed722ecd40ecdda92d705d211Erik                oldVersion += 1;
1241a6357118c223d00ed722ecd40ecdda92d705d211Erik            }
1242a6357118c223d00ed722ecd40ecdda92d705d211Erik            if (oldVersion == 60) {
1243a6357118c223d00ed722ecd40ecdda92d705d211Erik                upgradeToVersion61(db);
1244a6357118c223d00ed722ecd40ecdda92d705d211Erik                oldVersion += 1;
1245a6357118c223d00ed722ecd40ecdda92d705d211Erik            }
1246a6357118c223d00ed722ecd40ecdda92d705d211Erik            if (oldVersion == 61) {
1247a6357118c223d00ed722ecd40ecdda92d705d211Erik                upgradeToVersion62(db);
1248a6357118c223d00ed722ecd40ecdda92d705d211Erik                oldVersion += 1;
1249a6357118c223d00ed722ecd40ecdda92d705d211Erik            }
1250a6357118c223d00ed722ecd40ecdda92d705d211Erik            if (oldVersion == 62) {
12512cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                createEventsView = true;
1252a6357118c223d00ed722ecd40ecdda92d705d211Erik                oldVersion += 1;
1253a6357118c223d00ed722ecd40ecdda92d705d211Erik            }
1254a6357118c223d00ed722ecd40ecdda92d705d211Erik            if (oldVersion == 63) {
1255a6357118c223d00ed722ecd40ecdda92d705d211Erik                upgradeToVersion64(db);
1256a6357118c223d00ed722ecd40ecdda92d705d211Erik                oldVersion += 1;
1257a6357118c223d00ed722ecd40ecdda92d705d211Erik            }
1258a6357118c223d00ed722ecd40ecdda92d705d211Erik            if (oldVersion == 64) {
12592cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                createEventsView = true;
1260a6357118c223d00ed722ecd40ecdda92d705d211Erik                oldVersion += 1;
1261a6357118c223d00ed722ecd40ecdda92d705d211Erik            }
1262a6357118c223d00ed722ecd40ecdda92d705d211Erik            if (oldVersion == 65) {
1263a6357118c223d00ed722ecd40ecdda92d705d211Erik                upgradeToVersion66(db);
1264a6357118c223d00ed722ecd40ecdda92d705d211Erik                oldVersion += 1;
1265a6357118c223d00ed722ecd40ecdda92d705d211Erik            }
12661599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio            if (oldVersion == 66) {
1267679d544f38aa33d00c12884b987d8f8af2a6a6d3Fabrice Di Meglio                // Changes are done thru recreateMetaDataAndInstances() method
12681599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio                oldVersion += 1;
12691599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio            }
1270679d544f38aa33d00c12884b987d8f8af2a6a6d3Fabrice Di Meglio            if (recreateMetaDataAndInstances) {
12712cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                recreateMetaDataAndInstances67(db);
1272679d544f38aa33d00c12884b987d8f8af2a6a6d3Fabrice Di Meglio            }
127343b3eba05ef67bdd4b0a2b285b6ed2b377c136c5Fabrice Di Meglio            if (oldVersion == 67 || oldVersion == 68) {
1274e3730b9dce00439666e7ef324a28263a0ee92032Erik                upgradeToVersion69(db);
1275e3730b9dce00439666e7ef324a28263a0ee92032Erik                oldVersion = 69;
12767b40dde3168f4af2c757cb43955aa3bfe1668666Erik            }
1277b492524403ca34b0cb03bfad6456909494479925Fabrice Di Meglio            // 69. 70 are for Froyo/old Gingerbread only and 100s are for Gingerbread only
1278b492524403ca34b0cb03bfad6456909494479925Fabrice Di Meglio            // 70 and 71 have been for Honeycomb but no more used
1279b492524403ca34b0cb03bfad6456909494479925Fabrice Di Meglio            // 72 and 73 and 74 were for Honeycomb only but are considered as obsolete for enabling
1280b492524403ca34b0cb03bfad6456909494479925Fabrice Di Meglio            // room for Froyo version numbers
1281b492524403ca34b0cb03bfad6456909494479925Fabrice Di Meglio            if(oldVersion == 69) {
1282315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio                upgradeToVersion200(db);
12832cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                createEventsView = true;
1284315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio                oldVersion = 200;
128543b3eba05ef67bdd4b0a2b285b6ed2b377c136c5Fabrice Di Meglio            }
1286b492524403ca34b0cb03bfad6456909494479925Fabrice Di Meglio            if (oldVersion == 70) {
1287b492524403ca34b0cb03bfad6456909494479925Fabrice Di Meglio                upgradeToVersion200(db);
1288b492524403ca34b0cb03bfad6456909494479925Fabrice Di Meglio                oldVersion = 200;
1289b492524403ca34b0cb03bfad6456909494479925Fabrice Di Meglio            }
1290b492524403ca34b0cb03bfad6456909494479925Fabrice Di Meglio            if (oldVersion == 100) {
12917544af675ce2fd78f33198e5e9194f2bc7bd129fAndy McFadden                // note we skip past v101 and v102
1292b492524403ca34b0cb03bfad6456909494479925Fabrice Di Meglio                upgradeToVersion200(db);
1293b492524403ca34b0cb03bfad6456909494479925Fabrice Di Meglio                oldVersion = 200;
1294c59a6b5d8ff6b941fc44e9181e668fe0ec7df088Fabrice Di Meglio            }
1295315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio            boolean need203Update = true;
12967544af675ce2fd78f33198e5e9194f2bc7bd129fAndy McFadden            if (oldVersion == 101 || oldVersion == 102) {
12977544af675ce2fd78f33198e5e9194f2bc7bd129fAndy McFadden                // v101 is v100 plus updateCalendarCacheTableTo203().
12987544af675ce2fd78f33198e5e9194f2bc7bd129fAndy McFadden                // v102 is v101 with Event._id changed to autoincrement.
12997544af675ce2fd78f33198e5e9194f2bc7bd129fAndy McFadden                // Upgrade to 200 and skip the 203 update.
13007544af675ce2fd78f33198e5e9194f2bc7bd129fAndy McFadden                upgradeToVersion200(db);
1301315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio                oldVersion = 200;
1302315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio                need203Update = false;
1303315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio            }
1304b492524403ca34b0cb03bfad6456909494479925Fabrice Di Meglio            if (oldVersion == 200) {
1305b492524403ca34b0cb03bfad6456909494479925Fabrice Di Meglio                upgradeToVersion201(db);
13067e7329964ddd60c98e93a7eda18b68944a630382Fabrice Di Meglio                oldVersion += 1;
13077e7329964ddd60c98e93a7eda18b68944a630382Fabrice Di Meglio            }
1308b492524403ca34b0cb03bfad6456909494479925Fabrice Di Meglio            if (oldVersion == 201) {
1309b492524403ca34b0cb03bfad6456909494479925Fabrice Di Meglio                upgradeToVersion202(db);
13102cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                createEventsView = true;
1311b492524403ca34b0cb03bfad6456909494479925Fabrice Di Meglio                oldVersion += 1;
1312b492524403ca34b0cb03bfad6456909494479925Fabrice Di Meglio            }
13137544af675ce2fd78f33198e5e9194f2bc7bd129fAndy McFadden            if (oldVersion == 202) {
13147544af675ce2fd78f33198e5e9194f2bc7bd129fAndy McFadden                if (need203Update) {
13157544af675ce2fd78f33198e5e9194f2bc7bd129fAndy McFadden                    upgradeToVersion203(db);
13167544af675ce2fd78f33198e5e9194f2bc7bd129fAndy McFadden                }
1317315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio                oldVersion += 1;
1318315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio            }
1319c4d44fd028e7f5f44f46439c3410dab3456e6d3fFabrice Di Meglio            if (oldVersion == 203) {
13202cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                createEventsView = true;
1321c4d44fd028e7f5f44f46439c3410dab3456e6d3fFabrice Di Meglio                oldVersion += 1;
1322c4d44fd028e7f5f44f46439c3410dab3456e6d3fFabrice Di Meglio            }
13237544af675ce2fd78f33198e5e9194f2bc7bd129fAndy McFadden            if (oldVersion == 206) {
13247544af675ce2fd78f33198e5e9194f2bc7bd129fAndy McFadden                // v206 exists only in HC (change Event._id to autoincrement).  Otherwise
13257544af675ce2fd78f33198e5e9194f2bc7bd129fAndy McFadden                // identical to v204, so back it up and let the upgrade path continue.
13267544af675ce2fd78f33198e5e9194f2bc7bd129fAndy McFadden                oldVersion -= 2;
13277544af675ce2fd78f33198e5e9194f2bc7bd129fAndy McFadden            }
13284067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden            if (oldVersion == 204) {
1329c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                // This is an ICS update, all following use 300+ versions.
13304067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                upgradeToVersion205(db);
13314067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                createEventsView = true;
13324067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                oldVersion += 1;
13334067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden            }
1334c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik            if (oldVersion == 205) {
1335c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                // Move ICS updates to 300 range
1336c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                upgradeToVersion300(db);
1337c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                createEventsView = true;
1338c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                oldVersion = 300;
1339c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik            }
134034c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik            if (oldVersion == 300) {
134134c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik                upgradeToVersion301(db);
134234c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik                createEventsView = true;
134334c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik                oldVersion++;
134434c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik            }
1345da641c374b00946f37bfe00e53bb292f4e0103d8RoboErik            if (oldVersion == 301) {
1346da641c374b00946f37bfe00e53bb292f4e0103d8RoboErik                upgradeToVersion302(db);
1347da641c374b00946f37bfe00e53bb292f4e0103d8RoboErik                oldVersion++;
1348da641c374b00946f37bfe00e53bb292f4e0103d8RoboErik            }
1349fa332ecedc0c340109811552407142f6e4f600b2RoboErik            if (oldVersion == 302) {
1350fa332ecedc0c340109811552407142f6e4f600b2RoboErik                upgradeToVersion303(db);
1351fa332ecedc0c340109811552407142f6e4f600b2RoboErik                oldVersion++;
1352fa332ecedc0c340109811552407142f6e4f600b2RoboErik                createEventsView = true;
1353fa332ecedc0c340109811552407142f6e4f600b2RoboErik            }
13549ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert            if (oldVersion == 303) {
13559ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                upgradeToVersion304(db);
13569ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                oldVersion++;
13579ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                createEventsView = true;
13589ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert            }
135902f97c538fc46a08d857d2c807c76fd0eec12493RoboErik            if (oldVersion == 304) {
136002f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                upgradeToVersion305(db);
136102f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                oldVersion++;
136202f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                createEventsView = true;
136302f97c538fc46a08d857d2c807c76fd0eec12493RoboErik            }
1364470aa5bc291ca33d51dda356f38ac2954026da9aAlon Albert            if (oldVersion == 305) {
1365470aa5bc291ca33d51dda356f38ac2954026da9aAlon Albert                upgradeToVersion306(db);
1366470aa5bc291ca33d51dda356f38ac2954026da9aAlon Albert                // force a sync to update edit url and etag
1367470aa5bc291ca33d51dda356f38ac2954026da9aAlon Albert                scheduleSync(null /* all accounts */, false, null);
1368470aa5bc291ca33d51dda356f38ac2954026da9aAlon Albert                oldVersion++;
1369470aa5bc291ca33d51dda356f38ac2954026da9aAlon Albert            }
1370935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            if (oldVersion == 306) {
1371935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden                upgradeToVersion307(db);
1372935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden                oldVersion++;
1373935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            }
13742f251c778c06d21ed7693a70f4a1268ff929242eRoboErik            if (oldVersion == 307) {
13752f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                upgradeToVersion308(db);
13762f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                oldVersion++;
13772f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                createEventsView = true;
13782f251c778c06d21ed7693a70f4a1268ff929242eRoboErik            }
1379c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert            if (oldVersion == 308) {
1380ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson                upgradeToVersion400(db);
1381c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                createEventsView = true;
1382ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson                oldVersion = 400;
1383ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson            }
1384ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson            // 309 was changed to 400 since it is the first change of the J release.
1385ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson            if (oldVersion == 309 || oldVersion == 400) {
1386ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson                upgradeToVersion401(db);
1387ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson                createEventsView = true;
1388ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson                oldVersion = 401;
1389c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert            }
1390bafe9de156292f65b1079dd1eb586669f573d9e6Michael Chan            if (oldVersion == 401) {
1391bafe9de156292f65b1079dd1eb586669f573d9e6Michael Chan                upgradeToVersion402(db);
1392bafe9de156292f65b1079dd1eb586669f573d9e6Michael Chan                createEventsView = true;
1393bafe9de156292f65b1079dd1eb586669f573d9e6Michael Chan                oldVersion = 402;
1394bafe9de156292f65b1079dd1eb586669f573d9e6Michael Chan            }
1395c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan            if (oldVersion == 402) {
1396c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan                upgradeToVersion403(db);
1397501e60bcb1b519d80723f7b64ba60bd079b8ec8dSara Ting                createEventsView = true;
1398c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan                oldVersion = 403;
1399c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan            }
1400b2695bf3cfb173c4c5ba7bfd3c93ba8a51d65810Alon Albert            if (oldVersion == 403) {
1401b2695bf3cfb173c4c5ba7bfd3c93ba8a51d65810Alon Albert                upgradeToVersion501(db);
1402501e60bcb1b519d80723f7b64ba60bd079b8ec8dSara Ting                createEventsView = true;
1403b2695bf3cfb173c4c5ba7bfd3c93ba8a51d65810Alon Albert                oldVersion = 501;
1404b2695bf3cfb173c4c5ba7bfd3c93ba8a51d65810Alon Albert            }
1405501e60bcb1b519d80723f7b64ba60bd079b8ec8dSara Ting            if (oldVersion == 501) {
1406501e60bcb1b519d80723f7b64ba60bd079b8ec8dSara Ting                upgradeToVersion502(db);
1407501e60bcb1b519d80723f7b64ba60bd079b8ec8dSara Ting                createEventsView = true; // This is needed if the calendars or events schema changed
1408501e60bcb1b519d80723f7b64ba60bd079b8ec8dSara Ting                oldVersion = 502;
1409501e60bcb1b519d80723f7b64ba60bd079b8ec8dSara Ting            }
14107a2531a4b68e9efe14353cc7f4a64a8c5613e5d3Alon Albert            if (oldVersion < 600) {
14117a2531a4b68e9efe14353cc7f4a64a8c5613e5d3Alon Albert                upgradeToVersion600(db);
14127a2531a4b68e9efe14353cc7f4a64a8c5613e5d3Alon Albert                createEventsView = true; // This is needed if the calendars or events schema changed
14137a2531a4b68e9efe14353cc7f4a64a8c5613e5d3Alon Albert                oldVersion = 600;
14147a2531a4b68e9efe14353cc7f4a64a8c5613e5d3Alon Albert            }
1415b2695bf3cfb173c4c5ba7bfd3c93ba8a51d65810Alon Albert
14162cff10f1a005bd7302245d4c680cf851193c3a97RoboErik            if (createEventsView) {
14172cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                createEventsView(db);
14182cff10f1a005bd7302245d4c680cf851193c3a97RoboErik            }
1419b492524403ca34b0cb03bfad6456909494479925Fabrice Di Meglio            if (oldVersion != DATABASE_VERSION) {
1420b492524403ca34b0cb03bfad6456909494479925Fabrice Di Meglio                Log.e(TAG, "Need to recreate Calendar schema because of "
1421b492524403ca34b0cb03bfad6456909494479925Fabrice Di Meglio                        + "unknown Calendar database version: " + oldVersion);
1422b492524403ca34b0cb03bfad6456909494479925Fabrice Di Meglio                dropTables(db);
1423b492524403ca34b0cb03bfad6456909494479925Fabrice Di Meglio                bootstrapDB(db);
1424b492524403ca34b0cb03bfad6456909494479925Fabrice Di Meglio                oldVersion = DATABASE_VERSION;
1425935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            } else {
1426935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden                removeOrphans(db);
1427b492524403ca34b0cb03bfad6456909494479925Fabrice Di Meglio            }
1428a6357118c223d00ed722ecd40ecdda92d705d211Erik        } catch (SQLiteException e) {
1429c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan            if (mInTestMode) {
1430c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan                // We do want to crash if we are in test mode.
1431c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan                throw e;
1432c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan            }
14337544af675ce2fd78f33198e5e9194f2bc7bd129fAndy McFadden            Log.e(TAG, "onUpgrade: SQLiteException, recreating db. ", e);
14347544af675ce2fd78f33198e5e9194f2bc7bd129fAndy McFadden            Log.e(TAG, "(oldVersion was " + oldVersion + ")");
1435a6357118c223d00ed722ecd40ecdda92d705d211Erik            dropTables(db);
1436a6357118c223d00ed722ecd40ecdda92d705d211Erik            bootstrapDB(db);
1437a6357118c223d00ed722ecd40ecdda92d705d211Erik            return; // this was lossy
1438bf897b03effb752368a98cfb89e6b90cfdde50fcMarc Blank        }
1439c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik
14407544af675ce2fd78f33198e5e9194f2bc7bd129fAndy McFadden        long endWhen = System.nanoTime();
14417544af675ce2fd78f33198e5e9194f2bc7bd129fAndy McFadden        Log.d(TAG, "Calendar upgrade took " + ((endWhen - startWhen) / 1000000) + "ms");
14427544af675ce2fd78f33198e5e9194f2bc7bd129fAndy McFadden
1443c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik        /**
1444c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik         * db versions < 100 correspond to Froyo and earlier. Gingerbread bumped
1445c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik         * the db versioning to 100. Honeycomb bumped it to 200. ICS will begin
1446c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik         * in 300. At each major release we should jump to the next
1447c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik         * centiversion.
1448c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik         */
1449ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff    }
1450ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff
14510d8699eedb0f3bcec1854b9753ae59154a122726Michael Chan    @Override
14520d8699eedb0f3bcec1854b9753ae59154a122726Michael Chan    public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
14530d8699eedb0f3bcec1854b9753ae59154a122726Michael Chan        Log.i(TAG, "Can't downgrade DB from version " + oldVersion + " to " + newVersion);
14540d8699eedb0f3bcec1854b9753ae59154a122726Michael Chan        dropTables(db);
14550d8699eedb0f3bcec1854b9753ae59154a122726Michael Chan        bootstrapDB(db);
14560d8699eedb0f3bcec1854b9753ae59154a122726Michael Chan        return;
14570d8699eedb0f3bcec1854b9753ae59154a122726Michael Chan    }
14580d8699eedb0f3bcec1854b9753ae59154a122726Michael Chan
14591599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio    /**
1460679d544f38aa33d00c12884b987d8f8af2a6a6d3Fabrice Di Meglio     * If the user_version of the database if between 59 and 66 (those versions has been deployed
1461679d544f38aa33d00c12884b987d8f8af2a6a6d3Fabrice Di Meglio     * with no primary key for the CalendarMetaData table)
14621599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio     */
14632cff10f1a005bd7302245d4c680cf851193c3a97RoboErik    private void recreateMetaDataAndInstances67(SQLiteDatabase db) {
1464679d544f38aa33d00c12884b987d8f8af2a6a6d3Fabrice Di Meglio        // Recreate the CalendarMetaData table with correct primary key
14652cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("DROP TABLE CalendarMetaData;");
14662cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        createCalendarMetaDataTable59(db);
1467679d544f38aa33d00c12884b987d8f8af2a6a6d3Fabrice Di Meglio
1468679d544f38aa33d00c12884b987d8f8af2a6a6d3Fabrice Di Meglio        // Also clean the Instance table as this table may be corrupted
14692cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("DELETE FROM Instances;");
1470ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff    }
1471ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff
14727b40dde3168f4af2c757cb43955aa3bfe1668666Erik    private static boolean fixAllDayTime(Time time, String timezone, Long timeInMillis) {
14737b40dde3168f4af2c757cb43955aa3bfe1668666Erik        time.set(timeInMillis);
14747b40dde3168f4af2c757cb43955aa3bfe1668666Erik        if(time.hour != 0 || time.minute != 0 || time.second != 0) {
14757b40dde3168f4af2c757cb43955aa3bfe1668666Erik            time.hour = 0;
14767b40dde3168f4af2c757cb43955aa3bfe1668666Erik            time.minute = 0;
14777b40dde3168f4af2c757cb43955aa3bfe1668666Erik            time.second = 0;
14787b40dde3168f4af2c757cb43955aa3bfe1668666Erik            return true;
14797b40dde3168f4af2c757cb43955aa3bfe1668666Erik        }
14807b40dde3168f4af2c757cb43955aa3bfe1668666Erik        return false;
14817b40dde3168f4af2c757cb43955aa3bfe1668666Erik    }
14827b40dde3168f4af2c757cb43955aa3bfe1668666Erik
1483ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson    /**********************************************************/
1484ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson    /* DO NOT USE CONSTANTS FOR UPGRADES, USE STRING LITERALS */
1485ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson    /**********************************************************/
1486ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson
1487ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson    /**********************************************************/
1488b2695bf3cfb173c4c5ba7bfd3c93ba8a51d65810Alon Albert    /* 6xx db version is for K release
1489b2695bf3cfb173c4c5ba7bfd3c93ba8a51d65810Alon Albert    /**********************************************************/
1490b2695bf3cfb173c4c5ba7bfd3c93ba8a51d65810Alon Albert
14917a2531a4b68e9efe14353cc7f4a64a8c5613e5d3Alon Albert    private void upgradeToVersion600(SQLiteDatabase db) {
14927a2531a4b68e9efe14353cc7f4a64a8c5613e5d3Alon Albert        /*
14937a2531a4b68e9efe14353cc7f4a64a8c5613e5d3Alon Albert         * Changes from version 5xx to 600:
14947a2531a4b68e9efe14353cc7f4a64a8c5613e5d3Alon Albert         * - add mutator columns to Events & calendars
14957a2531a4b68e9efe14353cc7f4a64a8c5613e5d3Alon Albert         */
14967a2531a4b68e9efe14353cc7f4a64a8c5613e5d3Alon Albert        db.execSQL("ALTER TABLE Events ADD COLUMN mutators TEXT;");
14977a2531a4b68e9efe14353cc7f4a64a8c5613e5d3Alon Albert        db.execSQL("ALTER TABLE Calendars ADD COLUMN mutators TEXT;");
14987a2531a4b68e9efe14353cc7f4a64a8c5613e5d3Alon Albert    }
14997a2531a4b68e9efe14353cc7f4a64a8c5613e5d3Alon Albert
1500b2695bf3cfb173c4c5ba7bfd3c93ba8a51d65810Alon Albert    /**********************************************************/
1501b2695bf3cfb173c4c5ba7bfd3c93ba8a51d65810Alon Albert    /* 5xx db version is for JB MR1 release
1502ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson    /**********************************************************/
1503ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson
1504b2695bf3cfb173c4c5ba7bfd3c93ba8a51d65810Alon Albert    private void upgradeToVersion501(SQLiteDatabase db) {
1505b2695bf3cfb173c4c5ba7bfd3c93ba8a51d65810Alon Albert        /*
1506b2695bf3cfb173c4c5ba7bfd3c93ba8a51d65810Alon Albert         * Changes from version 403 to 501:
1507b2695bf3cfb173c4c5ba7bfd3c93ba8a51d65810Alon Albert         * - add isOrganizer column to Events table
1508b2695bf3cfb173c4c5ba7bfd3c93ba8a51d65810Alon Albert         * - add isPrimary column to Calendars table
1509b2695bf3cfb173c4c5ba7bfd3c93ba8a51d65810Alon Albert         */
1510b2695bf3cfb173c4c5ba7bfd3c93ba8a51d65810Alon Albert        db.execSQL("ALTER TABLE Events ADD COLUMN isOrganizer INTEGER;");
1511b2695bf3cfb173c4c5ba7bfd3c93ba8a51d65810Alon Albert        db.execSQL("ALTER TABLE Calendars ADD COLUMN isPrimary INTEGER;");
1512b2695bf3cfb173c4c5ba7bfd3c93ba8a51d65810Alon Albert    }
1513b2695bf3cfb173c4c5ba7bfd3c93ba8a51d65810Alon Albert
1514501e60bcb1b519d80723f7b64ba60bd079b8ec8dSara Ting    private void upgradeToVersion502(SQLiteDatabase db) {
1515501e60bcb1b519d80723f7b64ba60bd079b8ec8dSara Ting        /*
1516501e60bcb1b519d80723f7b64ba60bd079b8ec8dSara Ting         * Changes from version 501 to 502:
1517501e60bcb1b519d80723f7b64ba60bd079b8ec8dSara Ting         * - add UID for events added from the RFC 2445 iCalendar format.
1518501e60bcb1b519d80723f7b64ba60bd079b8ec8dSara Ting         */
1519501e60bcb1b519d80723f7b64ba60bd079b8ec8dSara Ting        db.execSQL("ALTER TABLE Events ADD COLUMN uid2445 TEXT;");
1520501e60bcb1b519d80723f7b64ba60bd079b8ec8dSara Ting    }
1521501e60bcb1b519d80723f7b64ba60bd079b8ec8dSara Ting
1522ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson    /**********************************************************/
1523ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson    /* 4xx db version is for J release
1524ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson    /**********************************************************/
1525ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson
1526c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan    private void upgradeToVersion403(SQLiteDatabase db) {
1527c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan        /*
1528c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan         * Changes from version 402 to 403:
1529c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan         * - add custom app package name and uri Events table
1530c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan         */
1531c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan        db.execSQL("ALTER TABLE Events ADD COLUMN customAppPackage TEXT;");
1532c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan        db.execSQL("ALTER TABLE Events ADD COLUMN customAppUri TEXT;");
1533c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan    }
1534c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan
1535c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan    private void upgradeToVersion402(SQLiteDatabase db) {
1536bafe9de156292f65b1079dd1eb586669f573d9e6Michael Chan        /*
1537bafe9de156292f65b1079dd1eb586669f573d9e6Michael Chan         * Changes from version 401 to 402:
1538bafe9de156292f65b1079dd1eb586669f573d9e6Michael Chan         * - add identity and namespace to Attendees table
1539bafe9de156292f65b1079dd1eb586669f573d9e6Michael Chan         */
1540bafe9de156292f65b1079dd1eb586669f573d9e6Michael Chan        db.execSQL("ALTER TABLE Attendees ADD COLUMN attendeeIdentity TEXT;");
1541bafe9de156292f65b1079dd1eb586669f573d9e6Michael Chan        db.execSQL("ALTER TABLE Attendees ADD COLUMN attendeeIdNamespace TEXT;");
1542bafe9de156292f65b1079dd1eb586669f573d9e6Michael Chan    }
1543bafe9de156292f65b1079dd1eb586669f573d9e6Michael Chan
1544ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson    /*
1545ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson     * Changes from version 309 to 401:
1546ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson     * Fix repeating events' exceptions with the wrong original_id
1547ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson     */
1548ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson    private void upgradeToVersion401(SQLiteDatabase db) {
1549ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson        db.execSQL("UPDATE events SET original_id=(SELECT _id FROM events inner_events WHERE " +
1550ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson                "inner_events._sync_id=events.original_sync_id AND " +
1551ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson                "inner_events.calendar_id=events.calendar_id) WHERE NOT original_id IS NULL AND " +
1552ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson                "(SELECT calendar_id FROM events ex_events WHERE " +
1553ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson                "ex_events._id=events.original_id) <> calendar_id ");
1554ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson    }
1555ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson
1556ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson    private void upgradeToVersion400(SQLiteDatabase db) {
1557c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert        db.execSQL("DROP TRIGGER IF EXISTS calendar_color_update");
1558ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson        // CREATE_CALENDAR_COLOR_UPDATE_TRIGGER was inlined
1559ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson        db.execSQL("CREATE TRIGGER "
1560ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson                + "calendar_color_update" + " UPDATE OF " + Calendars.CALENDAR_COLOR_KEY
1561ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson                + " ON " + Tables.CALENDARS + " WHEN new." + Calendars.CALENDAR_COLOR_KEY
1562ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson                + " NOT NULL BEGIN " + "UPDATE " + Tables.CALENDARS
1563ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson                + " SET calendar_color=(SELECT " + Colors.COLOR + " FROM " + Tables.COLORS
1564ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson                + " WHERE " + Colors.ACCOUNT_NAME + "=" + "new." + Calendars.ACCOUNT_NAME + " AND "
1565ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson                + Colors.ACCOUNT_TYPE + "=" + "new." + Calendars.ACCOUNT_TYPE + " AND "
1566ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson                + Colors.COLOR_KEY + "=" + "new." + Calendars.CALENDAR_COLOR_KEY + " AND "
1567ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson                + Colors.COLOR_TYPE + "=" + Colors.TYPE_CALENDAR + ") "
1568ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson                + " WHERE " + Calendars._ID + "=" + "old." + Calendars._ID
1569ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson                + ";" + " END");
1570c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert        db.execSQL("DROP TRIGGER IF EXISTS event_color_update");
1571ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson        // CREATE_EVENT_COLOR_UPDATE_TRIGGER was inlined
1572ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson        db.execSQL("CREATE TRIGGER "
1573ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson                + "event_color_update" + " UPDATE OF " + Events.EVENT_COLOR_KEY + " ON "
1574ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson                + Tables.EVENTS + " WHEN new." + Events.EVENT_COLOR_KEY + " NOT NULL BEGIN "
1575ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson                + "UPDATE " + Tables.EVENTS
1576ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson                + " SET eventColor=(SELECT " + Colors.COLOR + " FROM " + Tables.COLORS + " WHERE "
1577ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson                + Colors.ACCOUNT_NAME + "=" + "(SELECT " + Calendars.ACCOUNT_NAME + " FROM "
1578ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson                + Tables.CALENDARS + " WHERE " + Calendars._ID + "=new." + Events.CALENDAR_ID
1579ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson                + ") AND " + Colors.ACCOUNT_TYPE + "=" + "(SELECT " + Calendars.ACCOUNT_TYPE
1580ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson                + " FROM " + Tables.CALENDARS + " WHERE " + Calendars._ID + "=new."
1581ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson                + Events.CALENDAR_ID + ") AND " + Colors.COLOR_KEY + "=" + "new."
1582ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson                + Events.EVENT_COLOR_KEY + " AND " + Colors.COLOR_TYPE + "="
1583ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson                + Colors.TYPE_EVENT + ") "
1584ff5d02de9fddecbd5649f243233514e256a705c2Isaac Katzenelson                + " WHERE " + Events._ID + "=" + "old." + Events._ID + ";" + " END");
1585c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert    }
1586c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert
1587c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan    private void upgradeToVersion308(SQLiteDatabase db) {
15882f251c778c06d21ed7693a70f4a1268ff929242eRoboErik        /*
15892f251c778c06d21ed7693a70f4a1268ff929242eRoboErik         * Changes from version 307 to 308:
15902f251c778c06d21ed7693a70f4a1268ff929242eRoboErik         * - add Colors table to db
15912f251c778c06d21ed7693a70f4a1268ff929242eRoboErik         * - add eventColor_index to Events table
15922f251c778c06d21ed7693a70f4a1268ff929242eRoboErik         * - add calendar_color_index to Calendars table
15932f251c778c06d21ed7693a70f4a1268ff929242eRoboErik         * - add allowedAttendeeTypes to Calendars table
15942f251c778c06d21ed7693a70f4a1268ff929242eRoboErik         * - add allowedAvailability to Calendars table
15952f251c778c06d21ed7693a70f4a1268ff929242eRoboErik         */
15962f251c778c06d21ed7693a70f4a1268ff929242eRoboErik        createColorsTable(db);
15972f251c778c06d21ed7693a70f4a1268ff929242eRoboErik
15982f251c778c06d21ed7693a70f4a1268ff929242eRoboErik        db.execSQL("ALTER TABLE Calendars ADD COLUMN allowedAvailability TEXT DEFAULT '0,1';");
15992f251c778c06d21ed7693a70f4a1268ff929242eRoboErik        db.execSQL("ALTER TABLE Calendars ADD COLUMN allowedAttendeeTypes TEXT DEFAULT '0,1,2';");
16002f251c778c06d21ed7693a70f4a1268ff929242eRoboErik        db.execSQL("ALTER TABLE Calendars ADD COLUMN calendar_color_index TEXT;");
16012f251c778c06d21ed7693a70f4a1268ff929242eRoboErik        db.execSQL("ALTER TABLE Events ADD COLUMN eventColor_index TEXT;");
16022f251c778c06d21ed7693a70f4a1268ff929242eRoboErik
16032f251c778c06d21ed7693a70f4a1268ff929242eRoboErik        // Default Exchange calendars to be supporting the 'tentative'
16042f251c778c06d21ed7693a70f4a1268ff929242eRoboErik        // availability as well
16052f251c778c06d21ed7693a70f4a1268ff929242eRoboErik        db.execSQL("UPDATE Calendars SET allowedAvailability='0,1,2' WHERE _id IN "
16062f251c778c06d21ed7693a70f4a1268ff929242eRoboErik                + "(SELECT _id FROM Calendars WHERE account_type='com.android.exchange');");
16072f251c778c06d21ed7693a70f4a1268ff929242eRoboErik
16082f251c778c06d21ed7693a70f4a1268ff929242eRoboErik        // Triggers to update the color stored in an event or a calendar when
16092f251c778c06d21ed7693a70f4a1268ff929242eRoboErik        // the color_index is changed.
16102f251c778c06d21ed7693a70f4a1268ff929242eRoboErik        createColorsTriggers(db);
16112f251c778c06d21ed7693a70f4a1268ff929242eRoboErik    }
16122f251c778c06d21ed7693a70f4a1268ff929242eRoboErik
1613c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan    private void upgradeToVersion307(SQLiteDatabase db) {
1614935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden        /*
1615935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden         * Changes from version 306 to 307:
1616935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden         * - Changed _id field to AUTOINCREMENT
1617935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden         */
1618935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden        db.execSQL("ALTER TABLE Events RENAME TO Events_Backup;");
1619935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden        db.execSQL("DROP TRIGGER IF EXISTS events_cleanup_delete");
1620935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden        db.execSQL("DROP TRIGGER IF EXISTS original_sync_update");
1621935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden        db.execSQL("DROP INDEX IF EXISTS eventsCalendarIdIndex");
16222f251c778c06d21ed7693a70f4a1268ff929242eRoboErik        createEventsTable307(db);
1623935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden
1624935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden        String FIELD_LIST =
1625935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "_id, " +
1626935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "_sync_id, " +
1627935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "dirty, " +
1628935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "lastSynced," +
1629935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "calendar_id, " +
1630935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "title, " +
1631935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "eventLocation, " +
1632935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "description, " +
1633935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "eventColor, " +
1634935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "eventStatus, " +
1635935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "selfAttendeeStatus, " +
1636935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "dtstart, " +
1637935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "dtend, " +
1638935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "eventTimezone, " +
1639935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "duration, " +
1640935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "allDay, " +
1641935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "accessLevel, " +
1642935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "availability, " +
1643935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "hasAlarm, " +
1644935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "hasExtendedProperties, " +
1645935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "rrule, " +
1646935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "rdate, " +
1647935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "exrule, " +
1648935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "exdate, " +
1649935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "original_id," +
1650935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "original_sync_id, " +
1651935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "originalInstanceTime, " +
1652935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "originalAllDay, " +
1653935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "lastDate, " +
1654935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "hasAttendeeData, " +
1655935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "guestsCanModify, " +
1656935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "guestsCanInviteOthers, " +
1657935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "guestsCanSeeGuests, " +
1658935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "organizer, " +
1659935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "deleted, " +
1660935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "eventEndTimezone, " +
1661935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "sync_data1," +
1662935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "sync_data2," +
1663935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "sync_data3," +
1664935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "sync_data4," +
1665935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "sync_data5," +
1666935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "sync_data6," +
1667935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "sync_data7," +
1668935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "sync_data8," +
1669935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "sync_data9," +
1670935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden            "sync_data10 ";
1671935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden
1672935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden        // copy fields from old to new
1673935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden        db.execSQL("INSERT INTO Events (" + FIELD_LIST + ") SELECT " + FIELD_LIST +
1674935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden                "FROM Events_Backup;");
1675935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden
1676935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden        db.execSQL("DROP TABLE Events_Backup;");
1677935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden
1678935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden        // Trigger to remove data tied to an event when we delete that event.
1679935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden        db.execSQL("CREATE TRIGGER events_cleanup_delete DELETE ON " + Tables.EVENTS + " " +
1680935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden                "BEGIN " + EVENTS_CLEANUP_TRIGGER_SQL + "END");
1681935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden
1682935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden        // Trigger to update exceptions when an original event updates its
1683935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden        // _sync_id
1684935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden        db.execSQL(CREATE_SYNC_ID_UPDATE_TRIGGER);
1685935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden    }
1686935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden
1687c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan    private void upgradeToVersion306(SQLiteDatabase db) {
1688470aa5bc291ca33d51dda356f38ac2954026da9aAlon Albert        /*
1689470aa5bc291ca33d51dda356f38ac2954026da9aAlon Albert        * The following changes are for google.com accounts only.
1690470aa5bc291ca33d51dda356f38ac2954026da9aAlon Albert        *
1691470aa5bc291ca33d51dda356f38ac2954026da9aAlon Albert        * Change event id's from ".../private/full/... to .../events/...
1692470aa5bc291ca33d51dda356f38ac2954026da9aAlon Albert        * Set Calendars.canPartiallyUpdate to 1 to support partial updates
1693470aa5bc291ca33d51dda356f38ac2954026da9aAlon Albert        * Nuke sync state so we re-sync with a fresh etag and edit url
16943ac8148cdc79bde4b009ccb6a9ffda77bdb547d3Andy McFadden        *
16953ac8148cdc79bde4b009ccb6a9ffda77bdb547d3Andy McFadden        * We need to drop the original_sync_update trigger because it fires whenever the
16963ac8148cdc79bde4b009ccb6a9ffda77bdb547d3Andy McFadden        * sync_id field is touched, and dramatically slows this operation.
1697470aa5bc291ca33d51dda356f38ac2954026da9aAlon Albert        */
16983ac8148cdc79bde4b009ccb6a9ffda77bdb547d3Andy McFadden        db.execSQL("DROP TRIGGER IF EXISTS original_sync_update");
1699470aa5bc291ca33d51dda356f38ac2954026da9aAlon Albert        db.execSQL("UPDATE Events SET "
1700470aa5bc291ca33d51dda356f38ac2954026da9aAlon Albert                + "_sync_id = REPLACE(_sync_id, '/private/full/', '/events/'), "
1701470aa5bc291ca33d51dda356f38ac2954026da9aAlon Albert                + "original_sync_id = REPLACE(original_sync_id, '/private/full/', '/events/') "
1702470aa5bc291ca33d51dda356f38ac2954026da9aAlon Albert                + "WHERE _id IN (SELECT Events._id FROM Events "
1703470aa5bc291ca33d51dda356f38ac2954026da9aAlon Albert                +    "JOIN Calendars ON Events.calendar_id = Calendars._id "
1704470aa5bc291ca33d51dda356f38ac2954026da9aAlon Albert                +    "WHERE account_type = 'com.google')"
1705470aa5bc291ca33d51dda356f38ac2954026da9aAlon Albert        );
17063ac8148cdc79bde4b009ccb6a9ffda77bdb547d3Andy McFadden        db.execSQL(CREATE_SYNC_ID_UPDATE_TRIGGER);
1707470aa5bc291ca33d51dda356f38ac2954026da9aAlon Albert
1708470aa5bc291ca33d51dda356f38ac2954026da9aAlon Albert        db.execSQL("UPDATE Calendars SET canPartiallyUpdate = 1 WHERE account_type = 'com.google'");
1709470aa5bc291ca33d51dda356f38ac2954026da9aAlon Albert
1710470aa5bc291ca33d51dda356f38ac2954026da9aAlon Albert        db.execSQL("DELETE FROM _sync_state WHERE account_type = 'com.google'");
1711470aa5bc291ca33d51dda356f38ac2954026da9aAlon Albert    }
1712470aa5bc291ca33d51dda356f38ac2954026da9aAlon Albert
1713c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan    private void upgradeToVersion305(SQLiteDatabase db) {
171402f97c538fc46a08d857d2c807c76fd0eec12493RoboErik        /*
171502f97c538fc46a08d857d2c807c76fd0eec12493RoboErik         * Changes from version 304 to 305:
171602f97c538fc46a08d857d2c807c76fd0eec12493RoboErik         * -Add CAL_SYNC columns up to 10
171702f97c538fc46a08d857d2c807c76fd0eec12493RoboErik         * -Rename Calendars.access_level to calendar_access_level
171802f97c538fc46a08d857d2c807c76fd0eec12493RoboErik         * -Rename calendars _sync_version to cal_sync7
171902f97c538fc46a08d857d2c807c76fd0eec12493RoboErik         * -Rename calendars _sync_time to cal_sync8
172002f97c538fc46a08d857d2c807c76fd0eec12493RoboErik         * -Rename displayName to calendar_displayName
172102f97c538fc46a08d857d2c807c76fd0eec12493RoboErik         * -Rename _sync_local_id to sync_data2
172202f97c538fc46a08d857d2c807c76fd0eec12493RoboErik         * -Rename htmlUri to sync_data3
172302f97c538fc46a08d857d2c807c76fd0eec12493RoboErik         * -Rename events _sync_version to sync_data4
172402f97c538fc46a08d857d2c807c76fd0eec12493RoboErik         * -Rename events _sync_time to sync_data5
172502f97c538fc46a08d857d2c807c76fd0eec12493RoboErik         * -Rename commentsUri to sync_data6
172602f97c538fc46a08d857d2c807c76fd0eec12493RoboErik         * -Migrate Events _sync_mark to sync_data8
172702f97c538fc46a08d857d2c807c76fd0eec12493RoboErik         * -Change sync_data2 from INTEGER to TEXT
172802f97c538fc46a08d857d2c807c76fd0eec12493RoboErik         * -Change sync_data8 from INTEGER to TEXT
172902f97c538fc46a08d857d2c807c76fd0eec12493RoboErik         * -Add SYNC_DATA columns up to 10
173002f97c538fc46a08d857d2c807c76fd0eec12493RoboErik         * -Add EVENT_COLOR to Events table
173102f97c538fc46a08d857d2c807c76fd0eec12493RoboErik         */
173202f97c538fc46a08d857d2c807c76fd0eec12493RoboErik
173302f97c538fc46a08d857d2c807c76fd0eec12493RoboErik        // rename old table, create new table with updated layout
173402f97c538fc46a08d857d2c807c76fd0eec12493RoboErik        db.execSQL("ALTER TABLE Calendars RENAME TO Calendars_Backup;");
173502f97c538fc46a08d857d2c807c76fd0eec12493RoboErik        db.execSQL("DROP TRIGGER IF EXISTS calendar_cleanup");
17362f251c778c06d21ed7693a70f4a1268ff929242eRoboErik        createCalendarsTable305(db);
173702f97c538fc46a08d857d2c807c76fd0eec12493RoboErik
173802f97c538fc46a08d857d2c807c76fd0eec12493RoboErik        // copy fields from old to new
173902f97c538fc46a08d857d2c807c76fd0eec12493RoboErik        db.execSQL("INSERT INTO Calendars (" +
174002f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "_id, " +
174102f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "account_name, " +
174202f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "account_type, " +
174302f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "_sync_id, " +
174402f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "cal_sync7, " +             // rename from _sync_version
174502f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "cal_sync8, " +             // rename from _sync_time
174602f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "dirty, " +
174702f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "name, " +
174802f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "calendar_displayName, " +  // rename from displayName
174902f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "calendar_color, " +
175002f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "calendar_access_level, " + // rename from access_level
175102f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "visible, " +
175202f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "sync_events, " +
175302f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "calendar_location, " +
175402f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "calendar_timezone, " +
175502f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "ownerAccount, " +
175602f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "canOrganizerRespond, " +
175702f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "canModifyTimeZone, " +
175802f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "maxReminders, " +
175902f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "allowedReminders, " +
176002f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "deleted, " +
176102f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "canPartiallyUpdate," +
176202f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "cal_sync1, " +
176302f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "cal_sync2, " +
176402f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "cal_sync3, " +
176502f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "cal_sync4, " +
176602f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "cal_sync5, " +
176702f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "cal_sync6) " +
176802f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "SELECT " +
176902f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "_id, " +
177002f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "account_name, " +
177102f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "account_type, " +
177202f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "_sync_id, " +
177302f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "_sync_version, " +
177402f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "_sync_time, " +
177502f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "dirty, " +
177602f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "name, " +
177702f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "displayName, " +
177802f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "calendar_color, " +
177902f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "access_level, " +
178002f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "visible, " +
178102f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "sync_events, " +
178202f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "calendar_location, " +
178302f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "calendar_timezone, " +
178402f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "ownerAccount, " +
178502f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "canOrganizerRespond, " +
178602f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "canModifyTimeZone, " +
178702f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "maxReminders, " +
178802f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "allowedReminders, " +
178902f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "deleted, " +
179002f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "canPartiallyUpdate," +
179102f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "cal_sync1, " +
179202f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "cal_sync2, " +
179302f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "cal_sync3, " +
179402f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "cal_sync4, " +
179502f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "cal_sync5, " +
179602f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "cal_sync6 " +
179702f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "FROM Calendars_Backup;");
179802f97c538fc46a08d857d2c807c76fd0eec12493RoboErik
179902f97c538fc46a08d857d2c807c76fd0eec12493RoboErik        // drop the old table
180002f97c538fc46a08d857d2c807c76fd0eec12493RoboErik        db.execSQL("DROP TABLE Calendars_Backup;");
180102f97c538fc46a08d857d2c807c76fd0eec12493RoboErik
180202f97c538fc46a08d857d2c807c76fd0eec12493RoboErik        db.execSQL("ALTER TABLE Events RENAME TO Events_Backup;");
180302f97c538fc46a08d857d2c807c76fd0eec12493RoboErik        db.execSQL("DROP TRIGGER IF EXISTS events_cleanup_delete");
180402f97c538fc46a08d857d2c807c76fd0eec12493RoboErik        db.execSQL("DROP INDEX IF EXISTS eventsCalendarIdIndex");
1805935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden        // 305 and 307 can share the same createEventsTable implementation, because the
1806935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden        // addition of "autoincrement" to _ID doesn't affect the upgrade path.  (Note that
1807935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden        // much older databases may also already have autoincrement set because the change
1808935132618f821883f101db31af24e6d4c2b1e82cAndy McFadden        // was back-ported.)
18092f251c778c06d21ed7693a70f4a1268ff929242eRoboErik        createEventsTable307(db);
181002f97c538fc46a08d857d2c807c76fd0eec12493RoboErik
181102f97c538fc46a08d857d2c807c76fd0eec12493RoboErik        // copy fields from old to new
181202f97c538fc46a08d857d2c807c76fd0eec12493RoboErik        db.execSQL("INSERT INTO Events (" +
181302f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "_id, " +
181402f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "_sync_id, " +
181502f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "sync_data4, " +        // renamed from _sync_version
181602f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "sync_data5, " +        // renamed from _sync_time
181702f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "sync_data2, " +        // renamed from _sync_local_id
181802f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "dirty, " +
181902f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "sync_data8, " +        // renamed from _sync_mark
182002f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "calendar_id, " +
182102f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "sync_data3, " +        // renamed from htmlUri
182202f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "title, " +
182302f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "eventLocation, " +
182402f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "description, " +
182502f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "eventStatus, " +
182602f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "selfAttendeeStatus, " +
182702f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "sync_data6, " +        // renamed from commentsUri
182802f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "dtstart, " +
182902f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "dtend, " +
183002f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "eventTimezone, " +
183102f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "eventEndTimezone, " +
183202f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "duration, " +
183302f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "allDay, " +
183402f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "accessLevel, " +
183502f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "availability, " +
183602f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "hasAlarm, " +
183702f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "hasExtendedProperties, " +
183802f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "rrule, " +
183902f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "rdate, " +
184002f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "exrule, " +
184102f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "exdate, " +
184202f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "original_id," +
184302f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "original_sync_id, " +
184402f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "originalInstanceTime, " +
184502f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "originalAllDay, " +
184602f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "lastDate, " +
184702f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "hasAttendeeData, " +
184802f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "guestsCanModify, " +
184902f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "guestsCanInviteOthers, " +
185002f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "guestsCanSeeGuests, " +
185102f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "organizer, " +
185202f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "deleted, " +
185302f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "sync_data7," +
185402f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "lastSynced," +
185502f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "sync_data1) " +
185602f97c538fc46a08d857d2c807c76fd0eec12493RoboErik
185702f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "SELECT " +
185802f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "_id, " +
185902f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "_sync_id, " +
186002f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "_sync_version, " +
186102f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "_sync_time, " +
186202f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "_sync_local_id, " +
186302f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "dirty, " +
186402f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "_sync_mark, " +
186502f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "calendar_id, " +
186602f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "htmlUri, " +
186702f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "title, " +
186802f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "eventLocation, " +
186902f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "description, " +
187002f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "eventStatus, " +
187102f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "selfAttendeeStatus, " +
187202f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "commentsUri, " +
187302f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "dtstart, " +
187402f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "dtend, " +
187502f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "eventTimezone, " +
187602f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "eventEndTimezone, " +
187702f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "duration, " +
187802f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "allDay, " +
187902f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "accessLevel, " +
188002f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "availability, " +
188102f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "hasAlarm, " +
188202f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "hasExtendedProperties, " +
188302f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "rrule, " +
188402f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "rdate, " +
188502f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "exrule, " +
188602f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "exdate, " +
188702f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "original_id," +
188802f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "original_sync_id, " +
188902f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "originalInstanceTime, " +
189002f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "originalAllDay, " +
189102f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "lastDate, " +
189202f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "hasAttendeeData, " +
189302f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "guestsCanModify, " +
189402f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "guestsCanInviteOthers, " +
189502f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "guestsCanSeeGuests, " +
189602f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "organizer, " +
189702f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "deleted, " +
189802f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "sync_data7," +
189902f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "lastSynced," +
190002f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "sync_data1 " +
190102f97c538fc46a08d857d2c807c76fd0eec12493RoboErik
190202f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "FROM Events_Backup;"
190302f97c538fc46a08d857d2c807c76fd0eec12493RoboErik        );
190402f97c538fc46a08d857d2c807c76fd0eec12493RoboErik
190502f97c538fc46a08d857d2c807c76fd0eec12493RoboErik        db.execSQL("DROP TABLE Events_Backup;");
190602f97c538fc46a08d857d2c807c76fd0eec12493RoboErik
190702f97c538fc46a08d857d2c807c76fd0eec12493RoboErik        // Trigger to remove data tied to an event when we delete that event.
190802f97c538fc46a08d857d2c807c76fd0eec12493RoboErik        db.execSQL("CREATE TRIGGER events_cleanup_delete DELETE ON " + Tables.EVENTS + " " +
190902f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "BEGIN " +
191002f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                EVENTS_CLEANUP_TRIGGER_SQL +
191102f97c538fc46a08d857d2c807c76fd0eec12493RoboErik                "END");
191202f97c538fc46a08d857d2c807c76fd0eec12493RoboErik
191302f97c538fc46a08d857d2c807c76fd0eec12493RoboErik        // Trigger to update exceptions when an original event updates its
191402f97c538fc46a08d857d2c807c76fd0eec12493RoboErik        // _sync_id
191502f97c538fc46a08d857d2c807c76fd0eec12493RoboErik        db.execSQL(CREATE_SYNC_ID_UPDATE_TRIGGER);
191602f97c538fc46a08d857d2c807c76fd0eec12493RoboErik    }
191702f97c538fc46a08d857d2c807c76fd0eec12493RoboErik
1918c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan    private void upgradeToVersion304(SQLiteDatabase db) {
19199ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert        /*
19209ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert         * Changes from version 303 to 304:
19219ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert         * - add canPartiallyUpdate to Calendars table
19229ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert         * - add sync_data7 to Calendars to Events table
19239ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert         * - add lastSynced to Calendars to Events table
19249ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert         */
19259ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert        db.execSQL("ALTER TABLE Calendars ADD COLUMN canPartiallyUpdate INTEGER DEFAULT 0;");
19269ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert        db.execSQL("ALTER TABLE Events ADD COLUMN sync_data7 TEXT;");
19279ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert        db.execSQL("ALTER TABLE Events ADD COLUMN lastSynced INTEGER DEFAULT 0;");
19289ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert    }
19299ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert
1930c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan    private void upgradeToVersion303(SQLiteDatabase db) {
1931fa332ecedc0c340109811552407142f6e4f600b2RoboErik        /*
1932fa332ecedc0c340109811552407142f6e4f600b2RoboErik         * Changes from version 302 to 303:
1933fa332ecedc0c340109811552407142f6e4f600b2RoboErik         * - change SYNCx columns to CAL_SYNCx
1934fa332ecedc0c340109811552407142f6e4f600b2RoboErik         */
1935fa332ecedc0c340109811552407142f6e4f600b2RoboErik
1936fa332ecedc0c340109811552407142f6e4f600b2RoboErik        // rename old table, create new table with updated layout
1937fa332ecedc0c340109811552407142f6e4f600b2RoboErik        db.execSQL("ALTER TABLE Calendars RENAME TO Calendars_Backup;");
1938fa332ecedc0c340109811552407142f6e4f600b2RoboErik        db.execSQL("DROP TRIGGER IF EXISTS calendar_cleanup");
19399ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert        createCalendarsTable303(db);
1940fa332ecedc0c340109811552407142f6e4f600b2RoboErik
1941fa332ecedc0c340109811552407142f6e4f600b2RoboErik        // copy fields from old to new
1942fa332ecedc0c340109811552407142f6e4f600b2RoboErik        db.execSQL("INSERT INTO Calendars (" +
1943fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "_id, " +
1944fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "account_name, " +
1945fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "account_type, " +
1946fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "_sync_id, " +
1947fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "_sync_version, " +
1948fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "_sync_time, " +
1949fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "dirty, " +
1950fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "name, " +
1951fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "displayName, " +
1952fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "calendar_color, " +
1953fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "access_level, " +
1954fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "visible, " +
1955fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "sync_events, " +
1956fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "calendar_location, " +
1957fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "calendar_timezone, " +
1958fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "ownerAccount, " +
1959fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "canOrganizerRespond, " +
1960fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "canModifyTimeZone, " +
1961fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "maxReminders, " +
1962fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "allowedReminders, " +
1963fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "deleted, " +
1964fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "cal_sync1, " +     // rename from sync1
1965fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "cal_sync2, " +     // rename from sync2
1966fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "cal_sync3, " +     // rename from sync3
1967fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "cal_sync4, " +     // rename from sync4
1968fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "cal_sync5, " +     // rename from sync5
1969fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "cal_sync6) " +     // rename from sync6
1970fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "SELECT " +
1971fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "_id, " +
1972fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "account_name, " +
1973fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "account_type, " +
1974fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "_sync_id, " +
1975fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "_sync_version, " +
1976fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "_sync_time, " +
1977fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "dirty, " +
1978fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "name, " +
1979fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "displayName, " +
1980fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "calendar_color, " +
1981fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "access_level, " +
1982fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "visible, " +
1983fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "sync_events, " +
1984fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "calendar_location, " +
1985fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "calendar_timezone, " +
1986fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "ownerAccount, " +
1987fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "canOrganizerRespond, " +
1988fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "canModifyTimeZone, " +
1989fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "maxReminders, " +
1990fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "allowedReminders," +
1991fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "deleted, " +
1992fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "sync1, " +
1993fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "sync2, " +
1994fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "sync3, " +
1995fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "sync4," +
1996fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "sync5," +
1997fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "sync6 " +
1998fa332ecedc0c340109811552407142f6e4f600b2RoboErik                "FROM Calendars_Backup;"
1999fa332ecedc0c340109811552407142f6e4f600b2RoboErik        );
2000fa332ecedc0c340109811552407142f6e4f600b2RoboErik
2001fa332ecedc0c340109811552407142f6e4f600b2RoboErik        // drop the old table
2002fa332ecedc0c340109811552407142f6e4f600b2RoboErik        db.execSQL("DROP TABLE Calendars_Backup;");
2003fa332ecedc0c340109811552407142f6e4f600b2RoboErik    }
2004fa332ecedc0c340109811552407142f6e4f600b2RoboErik
2005c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan    private void upgradeToVersion302(SQLiteDatabase db) {
2006da641c374b00946f37bfe00e53bb292f4e0103d8RoboErik        /*
2007da641c374b00946f37bfe00e53bb292f4e0103d8RoboErik         * Changes from version 301 to 302
2008da641c374b00946f37bfe00e53bb292f4e0103d8RoboErik         * - Move Exchange eventEndTimezone values to SYNC_DATA1
2009da641c374b00946f37bfe00e53bb292f4e0103d8RoboErik         */
2010da641c374b00946f37bfe00e53bb292f4e0103d8RoboErik        db.execSQL("UPDATE Events SET sync_data1=eventEndTimezone WHERE calendar_id IN "
2011da641c374b00946f37bfe00e53bb292f4e0103d8RoboErik                + "(SELECT _id FROM Calendars WHERE account_type='com.android.exchange');");
2012da641c374b00946f37bfe00e53bb292f4e0103d8RoboErik
2013da641c374b00946f37bfe00e53bb292f4e0103d8RoboErik        db.execSQL("UPDATE Events SET eventEndTimezone=NULL WHERE calendar_id IN "
2014da641c374b00946f37bfe00e53bb292f4e0103d8RoboErik                + "(SELECT _id FROM Calendars WHERE account_type='com.android.exchange');");
2015da641c374b00946f37bfe00e53bb292f4e0103d8RoboErik    }
2016da641c374b00946f37bfe00e53bb292f4e0103d8RoboErik
2017c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan    private void upgradeToVersion301(SQLiteDatabase db) {
201834c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik        /*
201934c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik         * Changes from version 300 to 301
202034c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik         * - Added original_id column to Events table
202134c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik         * - Added triggers to keep original_id and original_sync_id in sync
202234c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik         */
202334c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik
202434c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik        db.execSQL("DROP TRIGGER IF EXISTS " + SYNC_ID_UPDATE_TRIGGER_NAME + ";");
202534c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik
202634c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik        db.execSQL("ALTER TABLE Events ADD COLUMN original_id INTEGER;");
202734c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik
202834c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik        // Fill in the original_id for all events that have an original_sync_id
202934c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik        db.execSQL("UPDATE Events set original_id=" +
203034c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik                "(SELECT Events2._id FROM Events AS Events2 " +
203134c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik                        "WHERE Events2._sync_id=Events.original_sync_id) " +
203234c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik                "WHERE Events.original_sync_id NOT NULL");
203334c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik        // Trigger to update exceptions when an original event updates its
203434c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik        // _sync_id
203534c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik        db.execSQL(CREATE_SYNC_ID_UPDATE_TRIGGER);
203634c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik    }
203734c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik
2038c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan    private void upgradeToVersion300(SQLiteDatabase db) {
2039c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik
2040c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik        /*
2041c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik         * Changes from version 205 to 300:
2042c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik         * - rename _sync_account to account_name in Calendars table
2043c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik         * - remove _sync_account from Events table
2044c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik         * - rename _sync_account_type to account_type in Calendars table
2045c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik         * - remove _sync_account_type from Events table
2046c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik         * - rename _sync_dirty to dirty in Calendars/Events table
2047c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik         * - rename color to calendar_color in Calendars table
2048c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik         * - rename location to calendar_location in Calendars table
2049c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik         * - rename timezone to calendar_timezone in Calendars table
2050c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik         * - add allowedReminders in Calendars table
2051c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik         * - rename visibility to accessLevel in Events table
2052c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik         * - rename transparency to availability in Events table
2053c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik         * - rename originalEvent to original_sync_id in Events table
2054c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik         * - remove dtstart2 and dtend2 from Events table
2055c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik         * - rename syncAdapterData to sync_data1 in Events table
2056c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik         */
2057c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik
2058c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik        // rename old table, create new table with updated layout
2059c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik        db.execSQL("ALTER TABLE Calendars RENAME TO Calendars_Backup;");
206034c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik        db.execSQL("DROP TRIGGER IF EXISTS calendar_cleanup;");
2061fa332ecedc0c340109811552407142f6e4f600b2RoboErik        createCalendarsTable300(db);
2062c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik
2063c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik        // copy fields from old to new
2064c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik        db.execSQL("INSERT INTO Calendars (" +
2065c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "_id, " +
2066c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "account_name, " +          // rename from _sync_account
2067c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "account_type, " +          // rename from _sync_account_type
2068c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "_sync_id, " +
2069c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "_sync_version, " +
2070c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "_sync_time, " +
2071c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "dirty, " +                 // rename from _sync_dirty
2072c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "name, " +
2073c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "displayName, " +
2074c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "calendar_color, " +        // rename from color
2075c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "access_level, " +
2076c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "visible, " +
2077c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "sync_events, " +
2078c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "calendar_location, " +     // rename from location
2079c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "calendar_timezone, " +     // rename from timezone
2080c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "ownerAccount, " +
2081c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "canOrganizerRespond, " +
2082c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "canModifyTimeZone, " +
2083c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "maxReminders, " +
2084c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "allowedReminders," +
2085c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "deleted, " +
2086c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "sync1, " +
2087c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "sync2, " +
2088c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "sync3, " +
2089c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "sync4," +
2090c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "sync5," +
2091c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "sync6) " +
2092c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik
2093c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "SELECT " +
2094c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "_id, " +
2095c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "_sync_account, " +
2096c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "_sync_account_type, " +
2097c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "_sync_id, " +
2098c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "_sync_version, " +
2099c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "_sync_time, " +
2100c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "_sync_dirty, " +
2101c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "name, " +
2102c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "displayName, " +
2103c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "color, " +
2104c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "access_level, " +
2105c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "visible, " +
2106c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "sync_events, " +
2107c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "location, " +
2108c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "timezone, " +
2109c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "ownerAccount, " +
2110c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "canOrganizerRespond, " +
2111c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "canModifyTimeZone, " +
2112c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "maxReminders, " +
2113c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "'0,1,2,3'," +
2114c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "deleted, " +
2115c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "sync1, " +
2116c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "sync2, " +
2117c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "sync3, " +
2118c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "sync4, " +
2119c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "sync5, " +
2120c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "sync6 " +
2121c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "FROM Calendars_Backup;"
2122c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik        );
2123c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik
2124bf986d8deeeed9566e0badeba89d4800533cbca6Andy McFadden        /* expand the set of allowed reminders for Google calendars to include email */
2125bf986d8deeeed9566e0badeba89d4800533cbca6Andy McFadden        db.execSQL("UPDATE Calendars SET allowedReminders = '0,1,2' " +
2126bf986d8deeeed9566e0badeba89d4800533cbca6Andy McFadden                "WHERE account_type = 'com.google'");
2127bf986d8deeeed9566e0badeba89d4800533cbca6Andy McFadden
2128c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik        // drop the old table
2129c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik        db.execSQL("DROP TABLE Calendars_Backup;");
2130c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik
2131c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik        db.execSQL("ALTER TABLE Events RENAME TO Events_Backup;");
2132c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik        db.execSQL("DROP TRIGGER IF EXISTS events_insert");
2133c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik        db.execSQL("DROP TRIGGER IF EXISTS events_cleanup_delete");
2134c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik        db.execSQL("DROP INDEX IF EXISTS eventSyncAccountAndIdIndex");
2135c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik        db.execSQL("DROP INDEX IF EXISTS eventsCalendarIdIndex");
213634c32cd924eb8ee28381106b37044b78fd8cbc30RoboErik        createEventsTable300(db);
2137c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik
2138c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik        // copy fields from old to new
2139c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik        db.execSQL("INSERT INTO Events (" +
2140c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "_id, " +
2141c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "_sync_id, " +
2142c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "_sync_version, " +
2143c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "_sync_time, " +
2144c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "_sync_local_id, " +
2145c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "dirty, " +                 // renamed from _sync_dirty
2146c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "_sync_mark, " +
2147c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "calendar_id, " +
2148c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "htmlUri, " +
2149c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "title, " +
2150c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "eventLocation, " +
2151c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "description, " +
2152c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "eventStatus, " +
2153c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "selfAttendeeStatus, " +
2154c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "commentsUri, " +
2155c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "dtstart, " +
2156c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "dtend, " +
2157c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "eventTimezone, " +
2158c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "eventEndTimezone, " +      // renamed from eventTimezone2
2159c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "duration, " +
2160c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "allDay, " +
2161c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "accessLevel, " +           // renamed from visibility
2162c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "availability, " +          // renamed from transparency
2163c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "hasAlarm, " +
2164c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "hasExtendedProperties, " +
2165c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "rrule, " +
2166c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "rdate, " +
2167c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "exrule, " +
2168c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "exdate, " +
2169c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "original_sync_id, " +      // renamed from originalEvent
2170c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "originalInstanceTime, " +
2171c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "originalAllDay, " +
2172c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "lastDate, " +
2173c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "hasAttendeeData, " +
2174c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "guestsCanModify, " +
2175c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "guestsCanInviteOthers, " +
2176c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "guestsCanSeeGuests, " +
2177c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "organizer, " +
2178c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "deleted, " +
2179c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "sync_data1) " +             // renamed from syncAdapterData
2180c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik
2181c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "SELECT " +
2182c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "_id, " +
2183c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "_sync_id, " +
2184c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "_sync_version, " +
2185c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "_sync_time, " +
2186c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "_sync_local_id, " +
2187c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "_sync_dirty, " +
2188c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "_sync_mark, " +
2189c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "calendar_id, " +
2190c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "htmlUri, " +
2191c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "title, " +
2192c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "eventLocation, " +
2193c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "description, " +
2194c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "eventStatus, " +
2195c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "selfAttendeeStatus, " +
2196c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "commentsUri, " +
2197c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "dtstart, " +
2198c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "dtend, " +
2199c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "eventTimezone, " +
2200c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "eventTimezone2, " +
2201c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "duration, " +
2202c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "allDay, " +
2203c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "visibility, " +
2204c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "transparency, " +
2205c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "hasAlarm, " +
2206c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "hasExtendedProperties, " +
2207c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "rrule, " +
2208c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "rdate, " +
2209c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "exrule, " +
2210c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "exdate, " +
2211c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "originalEvent, " +
2212c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "originalInstanceTime, " +
2213c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "originalAllDay, " +
2214c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "lastDate, " +
2215c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "hasAttendeeData, " +
2216c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "guestsCanModify, " +
2217c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "guestsCanInviteOthers, " +
2218c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "guestsCanSeeGuests, " +
2219c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "organizer, " +
2220c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "deleted, " +
2221c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "syncAdapterData " +
2222c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik
2223c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "FROM Events_Backup;"
2224c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik        );
2225c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik
2226c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik        db.execSQL("DROP TABLE Events_Backup;");
2227c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik
2228c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik        // Trigger to remove data tied to an event when we delete that event.
2229c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik        db.execSQL("CREATE TRIGGER events_cleanup_delete DELETE ON " + Tables.EVENTS + " " +
2230c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "BEGIN " +
2231c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                EVENTS_CLEANUP_TRIGGER_SQL +
2232c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik                "END");
2233c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik
2234fa332ecedc0c340109811552407142f6e4f600b2RoboErik    }
2235c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik
2236c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan    private void upgradeToVersion205(SQLiteDatabase db) {
22374067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden        /*
22384067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden         * Changes from version 204 to 205:
22394067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden         * - rename+reorder "_sync_mark" to "sync6" (and change type from INTEGER to TEXT)
22404067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden         * - rename "selected" to "visible"
22414067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden         * - rename "organizerCanRespond" to "canOrganizerRespond"
22424067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden         * - add "canModifyTimeZone"
22434067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden         * - add "maxReminders"
22444067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden         * - remove "_sync_local_id" (a/k/a _SYNC_DATA)
22454067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden         */
22464067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden
22474067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden        // rename old table, create new table with updated layout
22484067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden        db.execSQL("ALTER TABLE Calendars RENAME TO Calendars_Backup;");
22494067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden        db.execSQL("DROP TRIGGER IF EXISTS calendar_cleanup");
2250c8383567db3ade2aea28447ad3bd09ac3033bcd7RoboErik        createCalendarsTable205(db);
22514067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden
22524067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden        // copy fields from old to new
22534067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden        db.execSQL("INSERT INTO Calendars (" +
22544067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "_id, " +
22554067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "_sync_account, " +
22564067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "_sync_account_type, " +
22574067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "_sync_id, " +
22584067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "_sync_version, " +
22594067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "_sync_time, " +
22604067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "_sync_dirty, " +
22614067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "name, " +
22624067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "displayName, " +
22634067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "color, " +
22644067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "access_level, " +
22654067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "visible, " +                   // rename from "selected"
22664067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "sync_events, " +
22674067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "location, " +
22684067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "timezone, " +
22694067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "ownerAccount, " +
22704067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "canOrganizerRespond, " +       // rename from "organizerCanRespond"
22714067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "canModifyTimeZone, " +
22724067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "maxReminders, " +
22734067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "deleted, " +
22744067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "sync1, " +
22754067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "sync2, " +
22764067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "sync3, " +
22774067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "sync4," +
22784067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "sync5," +
22794067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "sync6) " +                     // rename/reorder from _sync_mark
22804067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "SELECT " +
22814067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "_id, " +
22824067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "_sync_account, " +
22834067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "_sync_account_type, " +
22844067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "_sync_id, " +
22854067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "_sync_version, " +
22864067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "_sync_time, " +
22874067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "_sync_dirty, " +
22884067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "name, " +
22894067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "displayName, " +
22904067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "color, " +
22914067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "access_level, " +
22924067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "selected, " +
22934067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "sync_events, " +
22944067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "location, " +
22954067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "timezone, " +
22964067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "ownerAccount, " +
22974067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "organizerCanRespond, " +
22984067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "1, " +
22994067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "5, " +
23004067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "deleted, " +
23014067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "sync1, " +
23024067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "sync2, " +
23034067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "sync3, " +
23044067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "sync4, " +
23054067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "sync5, " +
23064067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "_sync_mark " +
23074067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "FROM Calendars_Backup;"
23084067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden        );
23094067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden
23104067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden        // set these fields appropriately for Exchange events
23114067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden        db.execSQL("UPDATE Calendars SET canModifyTimeZone=0, maxReminders=1 " +
23124067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden                "WHERE _sync_account_type='com.android.exchange'");
23134067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden
23144067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden        // drop the old table
23154067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden        db.execSQL("DROP TABLE Calendars_Backup;");
23164067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden    }
23174067700dbedcf4c8a379c9ecba9b5603972b4607Andy McFadden
2318c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan    private void upgradeToVersion203(SQLiteDatabase db) {
2319315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        // Same as Gingerbread version 100
23202cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        Cursor cursor = db.rawQuery("SELECT value FROM CalendarCache WHERE key=?",
2321315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio                new String[] {"timezoneDatabaseVersion"});
2322315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio
2323315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        String oldTimezoneDbVersion = null;
23240332925aa9db8c4826327edd85030a4791b7a8e6Michael Chan        if (cursor != null) {
232558313767dd0e7e3823c35ca61b40eddb9dd229bbFabrice Di Meglio            try {
23260332925aa9db8c4826327edd85030a4791b7a8e6Michael Chan                if (cursor.moveToNext()) {
23270332925aa9db8c4826327edd85030a4791b7a8e6Michael Chan                    oldTimezoneDbVersion = cursor.getString(0);
23280332925aa9db8c4826327edd85030a4791b7a8e6Michael Chan                    cursor.close();
23290332925aa9db8c4826327edd85030a4791b7a8e6Michael Chan                    cursor = null;
23300332925aa9db8c4826327edd85030a4791b7a8e6Michael Chan                    // Also clean the CalendarCache table
23310332925aa9db8c4826327edd85030a4791b7a8e6Michael Chan                    db.execSQL("DELETE FROM CalendarCache;");
23320332925aa9db8c4826327edd85030a4791b7a8e6Michael Chan                }
233358313767dd0e7e3823c35ca61b40eddb9dd229bbFabrice Di Meglio            } finally {
23340332925aa9db8c4826327edd85030a4791b7a8e6Michael Chan                if (cursor != null) {
23350332925aa9db8c4826327edd85030a4791b7a8e6Michael Chan                    cursor.close();
23360332925aa9db8c4826327edd85030a4791b7a8e6Michael Chan                }
233758313767dd0e7e3823c35ca61b40eddb9dd229bbFabrice Di Meglio            }
2338315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        }
23392cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        initCalendarCacheTable203(db, oldTimezoneDbVersion);
2340315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio
2341315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        // Same as Gingerbread version 101
2342315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        updateCalendarCacheTableTo203(db);
2343315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio    }
2344315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio
2345c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan    private void upgradeToVersion202(SQLiteDatabase db) {
23467e7329964ddd60c98e93a7eda18b68944a630382Fabrice Di Meglio        // We will drop the "hidden" column from the calendar schema and add the "sync5" column
23472cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("ALTER TABLE Calendars RENAME TO Calendars_Backup;");
23487e7329964ddd60c98e93a7eda18b68944a630382Fabrice Di Meglio
23497e7329964ddd60c98e93a7eda18b68944a630382Fabrice Di Meglio        db.execSQL("DROP TRIGGER IF EXISTS calendar_cleanup");
2350180076a810558478f55ade53ebef0a2ddfa6bbc0Andy McFadden        createCalendarsTable202(db);
23517e7329964ddd60c98e93a7eda18b68944a630382Fabrice Di Meglio
23527e7329964ddd60c98e93a7eda18b68944a630382Fabrice Di Meglio        // Populate the new Calendars table and put into the "sync5" column the value of the
23537e7329964ddd60c98e93a7eda18b68944a630382Fabrice Di Meglio        // old "hidden" column
23542cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("INSERT INTO Calendars (" +
23552cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_id, " +
23562cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_account, " +
23572cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_account_type, " +
23582cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_id, " +
23592cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_version, " +
23602cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_time, " +
23612cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_local_id, " +
23622cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_dirty, " +
23632cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_mark, " +
23642cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "name, " +
23652cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "displayName, " +
23662cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "color, " +
23672cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "access_level, " +
23682cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "selected, " +
23692cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "sync_events, " +
23702cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "location, " +
23712cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "timezone, " +
23722cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "ownerAccount, " +
23732cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "organizerCanRespond, " +
23742cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "deleted, " +
23752cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "sync1, " +
23762cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "sync2, " +
23772cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "sync3, " +
23782cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "sync4," +
23792cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "sync5) " +
23807e7329964ddd60c98e93a7eda18b68944a630382Fabrice Di Meglio                "SELECT " +
23812cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_id, " +
23822cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_account, " +
23832cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_account_type, " +
23842cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_id, " +
23852cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_version, " +
23862cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_time, " +
23872cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_local_id, " +
23882cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_dirty, " +
23892cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_mark, " +
23902cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "name, " +
23912cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "displayName, " +
23922cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "color, " +
23932cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "access_level, " +
23942cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "selected, " +
23952cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "sync_events, " +
23962cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "location, " +
23972cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "timezone, " +
23982cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "ownerAccount, " +
23992cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "organizerCanRespond, " +
24002cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "deleted, " +
24012cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "sync1, " +
24022cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "sync2, " +
24032cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "sync3, " +
24042cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "sync4, " +
24052cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "hidden " +
24062cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "FROM Calendars_Backup;"
24077e7329964ddd60c98e93a7eda18b68944a630382Fabrice Di Meglio        );
24087e7329964ddd60c98e93a7eda18b68944a630382Fabrice Di Meglio
24097e7329964ddd60c98e93a7eda18b68944a630382Fabrice Di Meglio        // Drop the backup table
24102cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("DROP TABLE Calendars_Backup;");
24117e7329964ddd60c98e93a7eda18b68944a630382Fabrice Di Meglio    }
24127e7329964ddd60c98e93a7eda18b68944a630382Fabrice Di Meglio
2413c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan    private void upgradeToVersion201(SQLiteDatabase db) {
24142cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("ALTER TABLE Calendars ADD COLUMN sync4 TEXT;");
2415836bc8e9da32b8231f1b0d57be271730d7a5368dFabrice Di Meglio    }
2416836bc8e9da32b8231f1b0d57be271730d7a5368dFabrice Di Meglio
2417c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan    private void upgradeToVersion200(SQLiteDatabase db) {
24181b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio        // we cannot use here a Calendar.Calendars,URL constant for "url" as we are trying to make
24191b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio        // it disappear so we are keeping the hardcoded name "url" in all the SQLs
24202cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("ALTER TABLE Calendars RENAME TO Calendars_Backup;");
24211b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio
24221fc162fc3a3bb466a39146cf59a8b51ec5d9de52Fabrice Di Meglio        db.execSQL("DROP TRIGGER IF EXISTS calendar_cleanup");
24232cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        createCalendarsTable200(db);
24241b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio
24251b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio        // Populate the new Calendars table except the SYNC2 / SYNC3 columns
24262cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("INSERT INTO Calendars (" +
24272cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_id, " +
24282cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_account, " +
24292cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_account_type, " +
24302cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_id, " +
24312cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_version, " +
24322cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_time, " +
24332cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_local_id, " +
24342cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_dirty, " +
24352cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_mark, " +
24362cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "name, " +
24372cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "displayName, " +
24382cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "color, " +
24392cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "access_level, " +
24402cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "selected, " +
24412cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "sync_events, " +
24422cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "location, " +
24432cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "timezone, " +
24442cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "ownerAccount, " +
24452cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "organizerCanRespond, " +
24462cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "deleted, " +
24472cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "sync1) " +
24481b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio                "SELECT " +
24492cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_id, " +
24502cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_account, " +
24512cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_account_type, " +
24522cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_id, " +
24532cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_version, " +
24542cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_time, " +
24552cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_local_id, " +
24562cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_dirty, " +
24572cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_mark, " +
24582cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "name, " +
24592cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "displayName, " +
24602cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "color, " +
24612cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "access_level, " +
24622cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "selected, " +
24632cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "sync_events, " +
24642cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "location, " +
24652cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "timezone, " +
24662cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "ownerAccount, " +
24672cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "organizerCanRespond, " +
24682cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "0, " +
24692cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "url " +
24702cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "FROM Calendars_Backup;"
24711b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio        );
24721b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio
24731b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio        // Populate SYNC2 and SYNC3 columns - SYNC1 represent the old "url" column
24741b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio        // We will need to iterate over all the "com.google" type of calendars
24752cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        String selectSql = "SELECT _id, url" +
24762cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                " FROM Calendars_Backup" +
24772cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                " WHERE _sync_account_type='com.google'" +
24781b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio                " AND url IS NOT NULL;";
24791b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio
24802cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        String updateSql = "UPDATE Calendars SET " +
24812cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "sync2=?, " + // edit Url
24822cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "sync3=? " + // self Url
24832cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "WHERE _id=?;";
24841b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio
24851b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio        Cursor cursor = db.rawQuery(selectSql, null /* selection args */);
24860332925aa9db8c4826327edd85030a4791b7a8e6Michael Chan        if (cursor != null) {
24871b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio            try {
24880332925aa9db8c4826327edd85030a4791b7a8e6Michael Chan                if (cursor.getCount() > 0) {
24890332925aa9db8c4826327edd85030a4791b7a8e6Michael Chan                    Object[] bindArgs = new Object[3];
24900332925aa9db8c4826327edd85030a4791b7a8e6Michael Chan                    while (cursor.moveToNext()) {
24910332925aa9db8c4826327edd85030a4791b7a8e6Michael Chan                        Long id = cursor.getLong(0);
24920332925aa9db8c4826327edd85030a4791b7a8e6Michael Chan                        String url = cursor.getString(1);
24930332925aa9db8c4826327edd85030a4791b7a8e6Michael Chan                        String selfUrl = getSelfUrlFromEventsUrl(url);
24940332925aa9db8c4826327edd85030a4791b7a8e6Michael Chan                        String editUrl = getEditUrlFromEventsUrl(url);
24950332925aa9db8c4826327edd85030a4791b7a8e6Michael Chan
24960332925aa9db8c4826327edd85030a4791b7a8e6Michael Chan                        bindArgs[0] = editUrl;
24970332925aa9db8c4826327edd85030a4791b7a8e6Michael Chan                        bindArgs[1] = selfUrl;
24980332925aa9db8c4826327edd85030a4791b7a8e6Michael Chan                        bindArgs[2] = id;
24990332925aa9db8c4826327edd85030a4791b7a8e6Michael Chan
25000332925aa9db8c4826327edd85030a4791b7a8e6Michael Chan                        db.execSQL(updateSql, bindArgs);
25010332925aa9db8c4826327edd85030a4791b7a8e6Michael Chan                    }
25021b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio                }
25031b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio            } finally {
25041b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio                cursor.close();
25051b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio            }
25061b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio        }
25071b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio
25081b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio        // Drop the backup table
25092cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("DROP TABLE Calendars_Backup;");
251043b3eba05ef67bdd4b0a2b285b6ed2b377c136c5Fabrice Di Meglio    }
251143b3eba05ef67bdd4b0a2b285b6ed2b377c136c5Fabrice Di Meglio
251243b3eba05ef67bdd4b0a2b285b6ed2b377c136c5Fabrice Di Meglio    @VisibleForTesting
2513c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan    public static void upgradeToVersion69(SQLiteDatabase db) {
25147b40dde3168f4af2c757cb43955aa3bfe1668666Erik        // Clean up allDay events which could be in an invalid state from an earlier version
25157b40dde3168f4af2c757cb43955aa3bfe1668666Erik        // Some allDay events had hour, min, sec not set to zero, which throws elsewhere. This
2516e3730b9dce00439666e7ef324a28263a0ee92032Erik        // will go through the allDay events and make sure they have proper values and are in the
2517e3730b9dce00439666e7ef324a28263a0ee92032Erik        // correct timezone. Verifies that dtstart and dtend are in UTC and at midnight, that
2518e3730b9dce00439666e7ef324a28263a0ee92032Erik        // eventTimezone is set to UTC, tries to make sure duration is in days, and that dtstart2
2519e3730b9dce00439666e7ef324a28263a0ee92032Erik        // and dtend2 are at midnight in their timezone.
25202cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        final String sql = "SELECT _id, " +
25212cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "dtstart, " +
25222cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "dtend, " +
25232cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "duration, " +
25242cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "dtstart2, " +
25252cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "dtend2, " +
25262cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "eventTimezone, " +
25272cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "eventTimezone2, " +
25282cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "rrule " +
25292cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "FROM Events " +
25302cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "WHERE allDay=?";
25317cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio        Cursor cursor = db.rawQuery(sql, new String[] {"1"});
25327b40dde3168f4af2c757cb43955aa3bfe1668666Erik        if (cursor != null) {
25337b40dde3168f4af2c757cb43955aa3bfe1668666Erik            try {
25347b40dde3168f4af2c757cb43955aa3bfe1668666Erik                String timezone;
25357b40dde3168f4af2c757cb43955aa3bfe1668666Erik                String timezone2;
25367b40dde3168f4af2c757cb43955aa3bfe1668666Erik                String duration;
25377b40dde3168f4af2c757cb43955aa3bfe1668666Erik                Long dtstart;
25387b40dde3168f4af2c757cb43955aa3bfe1668666Erik                Long dtstart2;
25397b40dde3168f4af2c757cb43955aa3bfe1668666Erik                Long dtend;
25407b40dde3168f4af2c757cb43955aa3bfe1668666Erik                Long dtend2;
25417b40dde3168f4af2c757cb43955aa3bfe1668666Erik                Time time = new Time();
25427b40dde3168f4af2c757cb43955aa3bfe1668666Erik                Long id;
2543e3730b9dce00439666e7ef324a28263a0ee92032Erik                // some things need to be in utc so we call this frequently, cache to make faster
2544e3730b9dce00439666e7ef324a28263a0ee92032Erik                final String utc = Time.TIMEZONE_UTC;
25457b40dde3168f4af2c757cb43955aa3bfe1668666Erik                while (cursor.moveToNext()) {
25467b40dde3168f4af2c757cb43955aa3bfe1668666Erik                    String rrule = cursor.getString(8);
25477b40dde3168f4af2c757cb43955aa3bfe1668666Erik                    id = cursor.getLong(0);
25487b40dde3168f4af2c757cb43955aa3bfe1668666Erik                    dtstart = cursor.getLong(1);
25497b40dde3168f4af2c757cb43955aa3bfe1668666Erik                    dtstart2 = null;
25507b40dde3168f4af2c757cb43955aa3bfe1668666Erik                    timezone = cursor.getString(6);
25517b40dde3168f4af2c757cb43955aa3bfe1668666Erik                    timezone2 = cursor.getString(7);
25527b40dde3168f4af2c757cb43955aa3bfe1668666Erik                    duration = cursor.getString(3);
25537b40dde3168f4af2c757cb43955aa3bfe1668666Erik
2554e3730b9dce00439666e7ef324a28263a0ee92032Erik                    if (TextUtils.isEmpty(rrule)) {
25557b40dde3168f4af2c757cb43955aa3bfe1668666Erik                        // For non-recurring events dtstart and dtend should both have values
25567b40dde3168f4af2c757cb43955aa3bfe1668666Erik                        // and duration should be null.
25577b40dde3168f4af2c757cb43955aa3bfe1668666Erik                        dtend = cursor.getLong(2);
25587b40dde3168f4af2c757cb43955aa3bfe1668666Erik                        dtend2 = null;
25597b40dde3168f4af2c757cb43955aa3bfe1668666Erik                        // Since we made all three of these at the same time if timezone2 exists
25607b40dde3168f4af2c757cb43955aa3bfe1668666Erik                        // so should dtstart2 and dtend2.
25617b40dde3168f4af2c757cb43955aa3bfe1668666Erik                        if(!TextUtils.isEmpty(timezone2)) {
25627b40dde3168f4af2c757cb43955aa3bfe1668666Erik                            dtstart2 = cursor.getLong(4);
25637b40dde3168f4af2c757cb43955aa3bfe1668666Erik                            dtend2 = cursor.getLong(5);
25647b40dde3168f4af2c757cb43955aa3bfe1668666Erik                        }
25657b40dde3168f4af2c757cb43955aa3bfe1668666Erik
25667b40dde3168f4af2c757cb43955aa3bfe1668666Erik                        boolean update = false;
2567e3730b9dce00439666e7ef324a28263a0ee92032Erik                        if (!TextUtils.equals(timezone, utc)) {
2568e3730b9dce00439666e7ef324a28263a0ee92032Erik                            update = true;
2569e3730b9dce00439666e7ef324a28263a0ee92032Erik                            timezone = utc;
2570e3730b9dce00439666e7ef324a28263a0ee92032Erik                        }
2571e3730b9dce00439666e7ef324a28263a0ee92032Erik
2572e3730b9dce00439666e7ef324a28263a0ee92032Erik                        time.clear(timezone);
2573e3730b9dce00439666e7ef324a28263a0ee92032Erik                        update |= fixAllDayTime(time, timezone, dtstart);
25747b40dde3168f4af2c757cb43955aa3bfe1668666Erik                        dtstart = time.normalize(false);
2575e3730b9dce00439666e7ef324a28263a0ee92032Erik
2576e3730b9dce00439666e7ef324a28263a0ee92032Erik                        time.clear(timezone);
25777b40dde3168f4af2c757cb43955aa3bfe1668666Erik                        update |= fixAllDayTime(time, timezone, dtend);
25787b40dde3168f4af2c757cb43955aa3bfe1668666Erik                        dtend = time.normalize(false);
25797b40dde3168f4af2c757cb43955aa3bfe1668666Erik
25807b40dde3168f4af2c757cb43955aa3bfe1668666Erik                        if (dtstart2 != null) {
2581e3730b9dce00439666e7ef324a28263a0ee92032Erik                            time.clear(timezone2);
25827b40dde3168f4af2c757cb43955aa3bfe1668666Erik                            update |= fixAllDayTime(time, timezone2, dtstart2);
25837b40dde3168f4af2c757cb43955aa3bfe1668666Erik                            dtstart2 = time.normalize(false);
25847b40dde3168f4af2c757cb43955aa3bfe1668666Erik                        }
25857b40dde3168f4af2c757cb43955aa3bfe1668666Erik
25867b40dde3168f4af2c757cb43955aa3bfe1668666Erik                        if (dtend2 != null) {
2587e3730b9dce00439666e7ef324a28263a0ee92032Erik                            time.clear(timezone2);
25887b40dde3168f4af2c757cb43955aa3bfe1668666Erik                            update |= fixAllDayTime(time, timezone2, dtend2);
25897b40dde3168f4af2c757cb43955aa3bfe1668666Erik                            dtend2 = time.normalize(false);
25907b40dde3168f4af2c757cb43955aa3bfe1668666Erik                        }
25917b40dde3168f4af2c757cb43955aa3bfe1668666Erik
25927b40dde3168f4af2c757cb43955aa3bfe1668666Erik                        if (!TextUtils.isEmpty(duration)) {
25937b40dde3168f4af2c757cb43955aa3bfe1668666Erik                            update = true;
25947b40dde3168f4af2c757cb43955aa3bfe1668666Erik                        }
25957b40dde3168f4af2c757cb43955aa3bfe1668666Erik
25967b40dde3168f4af2c757cb43955aa3bfe1668666Erik                        if (update) {
25977b40dde3168f4af2c757cb43955aa3bfe1668666Erik                            // enforce duration being null
25982cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                            db.execSQL("UPDATE Events SET " +
25992cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                                    "dtstart=?, " +
26002cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                                    "dtend=?, " +
26012cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                                    "dtstart2=?, " +
26022cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                                    "dtend2=?, " +
26032cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                                    "duration=?, " +
26042cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                                    "eventTimezone=?, " +
26052cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                                    "eventTimezone2=? " +
26062cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                                    "WHERE _id=?",
26077cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                                    new Object[] {
26087cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                                            dtstart,
26097cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                                            dtend,
26107cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                                            dtstart2,
26117cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                                            dtend2,
26127cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                                            null,
26137cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                                            timezone,
26147cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                                            timezone2,
26157cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                                            id}
26167cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                            );
26177b40dde3168f4af2c757cb43955aa3bfe1668666Erik                        }
26187b40dde3168f4af2c757cb43955aa3bfe1668666Erik
26197b40dde3168f4af2c757cb43955aa3bfe1668666Erik                    } else {
26207b40dde3168f4af2c757cb43955aa3bfe1668666Erik                        // For recurring events only dtstart and duration should be used.
26217b40dde3168f4af2c757cb43955aa3bfe1668666Erik                        // We ignore dtend since it will be overwritten if the event changes to a
26227b40dde3168f4af2c757cb43955aa3bfe1668666Erik                        // non-recurring event and won't be used otherwise.
26237b40dde3168f4af2c757cb43955aa3bfe1668666Erik                        if(!TextUtils.isEmpty(timezone2)) {
26247b40dde3168f4af2c757cb43955aa3bfe1668666Erik                            dtstart2 = cursor.getLong(4);
26257b40dde3168f4af2c757cb43955aa3bfe1668666Erik                        }
26267b40dde3168f4af2c757cb43955aa3bfe1668666Erik
26277b40dde3168f4af2c757cb43955aa3bfe1668666Erik                        boolean update = false;
2628e3730b9dce00439666e7ef324a28263a0ee92032Erik                        if (!TextUtils.equals(timezone, utc)) {
2629e3730b9dce00439666e7ef324a28263a0ee92032Erik                            update = true;
2630e3730b9dce00439666e7ef324a28263a0ee92032Erik                            timezone = utc;
2631e3730b9dce00439666e7ef324a28263a0ee92032Erik                        }
2632e3730b9dce00439666e7ef324a28263a0ee92032Erik
2633e3730b9dce00439666e7ef324a28263a0ee92032Erik                        time.clear(timezone);
2634e3730b9dce00439666e7ef324a28263a0ee92032Erik                        update |= fixAllDayTime(time, timezone, dtstart);
26357b40dde3168f4af2c757cb43955aa3bfe1668666Erik                        dtstart = time.normalize(false);
26367b40dde3168f4af2c757cb43955aa3bfe1668666Erik
26377b40dde3168f4af2c757cb43955aa3bfe1668666Erik                        if (dtstart2 != null) {
2638e3730b9dce00439666e7ef324a28263a0ee92032Erik                            time.clear(timezone2);
26397b40dde3168f4af2c757cb43955aa3bfe1668666Erik                            update |= fixAllDayTime(time, timezone2, dtstart2);
26407b40dde3168f4af2c757cb43955aa3bfe1668666Erik                            dtstart2 = time.normalize(false);
26417b40dde3168f4af2c757cb43955aa3bfe1668666Erik                        }
26427b40dde3168f4af2c757cb43955aa3bfe1668666Erik
26437b40dde3168f4af2c757cb43955aa3bfe1668666Erik                        if (TextUtils.isEmpty(duration)) {
26447b40dde3168f4af2c757cb43955aa3bfe1668666Erik                            // If duration was missing assume a 1 day duration
26457b40dde3168f4af2c757cb43955aa3bfe1668666Erik                            duration = "P1D";
26467b40dde3168f4af2c757cb43955aa3bfe1668666Erik                            update = true;
26477b40dde3168f4af2c757cb43955aa3bfe1668666Erik                        } else {
26487b40dde3168f4af2c757cb43955aa3bfe1668666Erik                            int len = duration.length();
26497b40dde3168f4af2c757cb43955aa3bfe1668666Erik                            // TODO fix durations in other formats as well
26507b40dde3168f4af2c757cb43955aa3bfe1668666Erik                            if (duration.charAt(0) == 'P' &&
26517b40dde3168f4af2c757cb43955aa3bfe1668666Erik                                    duration.charAt(len - 1) == 'S') {
26527b40dde3168f4af2c757cb43955aa3bfe1668666Erik                                int seconds = Integer.parseInt(duration.substring(1, len - 1));
26537b40dde3168f4af2c757cb43955aa3bfe1668666Erik                                int days = (seconds + DAY_IN_SECONDS - 1) / DAY_IN_SECONDS;
26547b40dde3168f4af2c757cb43955aa3bfe1668666Erik                                duration = "P" + days + "D";
26557b40dde3168f4af2c757cb43955aa3bfe1668666Erik                                update = true;
26567b40dde3168f4af2c757cb43955aa3bfe1668666Erik                            }
26577b40dde3168f4af2c757cb43955aa3bfe1668666Erik                        }
26587b40dde3168f4af2c757cb43955aa3bfe1668666Erik
26597b40dde3168f4af2c757cb43955aa3bfe1668666Erik                        if (update) {
26607b40dde3168f4af2c757cb43955aa3bfe1668666Erik                            // If there were other problems also enforce dtend being null
26612cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                            db.execSQL("UPDATE Events SET " +
26622cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                                    "dtstart=?, " +
26632cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                                    "dtend=?, " +
26642cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                                    "dtstart2=?, " +
26652cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                                    "dtend2=?, " +
26662cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                                    "duration=?," +
26672cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                                    "eventTimezone=?, " +
26682cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                                    "eventTimezone2=? " +
26692cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                                    "WHERE _id=?",
26707cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                                    new Object[] {
26717cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                                            dtstart,
26727cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                                            null,
26737cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                                            dtstart2,
26747cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                                            null,
26757cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                                            duration,
26767cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                                            timezone,
26777cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                                            timezone2,
26787cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                                            id}
26797cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                            );
26807b40dde3168f4af2c757cb43955aa3bfe1668666Erik                        }
26817b40dde3168f4af2c757cb43955aa3bfe1668666Erik                    }
26827b40dde3168f4af2c757cb43955aa3bfe1668666Erik                }
26837b40dde3168f4af2c757cb43955aa3bfe1668666Erik            } finally {
26847b40dde3168f4af2c757cb43955aa3bfe1668666Erik                cursor.close();
26857b40dde3168f4af2c757cb43955aa3bfe1668666Erik            }
26867b40dde3168f4af2c757cb43955aa3bfe1668666Erik        }
26877b40dde3168f4af2c757cb43955aa3bfe1668666Erik    }
26887b40dde3168f4af2c757cb43955aa3bfe1668666Erik
2689bf897b03effb752368a98cfb89e6b90cfdde50fcMarc Blank    private void upgradeToVersion66(SQLiteDatabase db) {
2690bf897b03effb752368a98cfb89e6b90cfdde50fcMarc Blank        // Add a column to indicate whether the event organizer can respond to his own events
2691bf897b03effb752368a98cfb89e6b90cfdde50fcMarc Blank        // The UI should not show attendee status for events in calendars with this column = 0
26922cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("ALTER TABLE Calendars" +
26932cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                " ADD COLUMN organizerCanRespond INTEGER NOT NULL DEFAULT 1;");
2694cf9dc6b9bd031b1f6f811a32326ee85429c94debMarc Blank    }
2695cf9dc6b9bd031b1f6f811a32326ee85429c94debMarc Blank
2696162c7c9bbd53b623fbe913b376e7f7f42915bb59Marc Blank    private void upgradeToVersion64(SQLiteDatabase db) {
2697162c7c9bbd53b623fbe913b376e7f7f42915bb59Marc Blank        // Add a column that may be used by sync adapters
26982cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("ALTER TABLE Events" +
26992cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                " ADD COLUMN syncAdapterData TEXT;");
27002d1b3d70a6ebce8194932f8a8355d97a89da113fFabrice Di Meglio    }
27012d1b3d70a6ebce8194932f8a8355d97a89da113fFabrice Di Meglio
2702ae4f20e120d3107cef20be860a612c9c23816295Erik    private void upgradeToVersion62(SQLiteDatabase db) {
2703ae4f20e120d3107cef20be860a612c9c23816295Erik        // New columns are to transition to having allDay events in the local timezone
27042cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("ALTER TABLE Events" +
27052cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                " ADD COLUMN dtstart2 INTEGER;");
27062cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("ALTER TABLE Events" +
27072cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                " ADD COLUMN dtend2 INTEGER;");
27082cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("ALTER TABLE Events" +
27092cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                " ADD COLUMN eventTimezone2 TEXT;");
2710ae4f20e120d3107cef20be860a612c9c23816295Erik
2711ae4f20e120d3107cef20be860a612c9c23816295Erik        String[] allDayBit = new String[] {"0"};
2712ae4f20e120d3107cef20be860a612c9c23816295Erik        // Copy over all the data that isn't an all day event.
27132cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("UPDATE Events SET " +
27142cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "dtstart2=dtstart," +
27152cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "dtend2=dtend," +
27162cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "eventTimezone2=eventTimezone " +
27172cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "WHERE allDay=?;",
2718ae4f20e120d3107cef20be860a612c9c23816295Erik                allDayBit /* selection args */);
2719ae4f20e120d3107cef20be860a612c9c23816295Erik
2720ae4f20e120d3107cef20be860a612c9c23816295Erik        // "cursor" iterates over all the calendars
2721ae4f20e120d3107cef20be860a612c9c23816295Erik        allDayBit[0] = "1";
27222cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        Cursor cursor = db.rawQuery("SELECT Events._id," +
27232cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "dtstart," +
27242cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "dtend," +
27252cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "eventTimezone," +
27262cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "timezone " +
27272cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "FROM Events INNER JOIN Calendars " +
27282cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "WHERE Events.calendar_id=Calendars._id" +
27292cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                " AND allDay=?",
2730ae4f20e120d3107cef20be860a612c9c23816295Erik                allDayBit /* selection args */);
2731ae4f20e120d3107cef20be860a612c9c23816295Erik
2732ae4f20e120d3107cef20be860a612c9c23816295Erik        Time oldTime = new Time();
2733ae4f20e120d3107cef20be860a612c9c23816295Erik        Time newTime = new Time();
2734ae4f20e120d3107cef20be860a612c9c23816295Erik        // Update the allday events in the new columns
2735ae4f20e120d3107cef20be860a612c9c23816295Erik        if (cursor != null) {
2736ae4f20e120d3107cef20be860a612c9c23816295Erik            try {
2737ae4f20e120d3107cef20be860a612c9c23816295Erik                String[] newData = new String[4];
2738ae4f20e120d3107cef20be860a612c9c23816295Erik                cursor.moveToPosition(-1);
2739ae4f20e120d3107cef20be860a612c9c23816295Erik                while (cursor.moveToNext()) {
2740ae4f20e120d3107cef20be860a612c9c23816295Erik                    long id = cursor.getLong(0); // Order from query above
2741ae4f20e120d3107cef20be860a612c9c23816295Erik                    long dtstart = cursor.getLong(1);
2742ae4f20e120d3107cef20be860a612c9c23816295Erik                    long dtend = cursor.getLong(2);
2743ae4f20e120d3107cef20be860a612c9c23816295Erik                    String eTz = cursor.getString(3); // current event timezone
2744ae4f20e120d3107cef20be860a612c9c23816295Erik                    String tz = cursor.getString(4); // Calendar timezone
2745dbaad88527665d5144a8a178fa822f58d2bc7d05Erik                    //If there's no timezone for some reason use UTC by default.
2746dbaad88527665d5144a8a178fa822f58d2bc7d05Erik                    if(eTz == null) {
2747dbaad88527665d5144a8a178fa822f58d2bc7d05Erik                        eTz = Time.TIMEZONE_UTC;
2748dbaad88527665d5144a8a178fa822f58d2bc7d05Erik                    }
2749ae4f20e120d3107cef20be860a612c9c23816295Erik
2750ae4f20e120d3107cef20be860a612c9c23816295Erik                    // Convert start time for all day events into the timezone of their calendar
2751ae4f20e120d3107cef20be860a612c9c23816295Erik                    oldTime.clear(eTz);
2752ae4f20e120d3107cef20be860a612c9c23816295Erik                    oldTime.set(dtstart);
2753ae4f20e120d3107cef20be860a612c9c23816295Erik                    newTime.clear(tz);
2754ae4f20e120d3107cef20be860a612c9c23816295Erik                    newTime.set(oldTime.monthDay, oldTime.month, oldTime.year);
2755ae4f20e120d3107cef20be860a612c9c23816295Erik                    newTime.normalize(false);
2756ae4f20e120d3107cef20be860a612c9c23816295Erik                    dtstart = newTime.toMillis(false /*ignoreDst*/);
2757ae4f20e120d3107cef20be860a612c9c23816295Erik
2758ae4f20e120d3107cef20be860a612c9c23816295Erik                    // Convert end time for all day events into the timezone of their calendar
2759ae4f20e120d3107cef20be860a612c9c23816295Erik                    oldTime.clear(eTz);
2760ae4f20e120d3107cef20be860a612c9c23816295Erik                    oldTime.set(dtend);
2761ae4f20e120d3107cef20be860a612c9c23816295Erik                    newTime.clear(tz);
2762ae4f20e120d3107cef20be860a612c9c23816295Erik                    newTime.set(oldTime.monthDay, oldTime.month, oldTime.year);
2763ae4f20e120d3107cef20be860a612c9c23816295Erik                    newTime.normalize(false);
2764ae4f20e120d3107cef20be860a612c9c23816295Erik                    dtend = newTime.toMillis(false /*ignoreDst*/);
2765ae4f20e120d3107cef20be860a612c9c23816295Erik
2766ae4f20e120d3107cef20be860a612c9c23816295Erik                    newData[0] = String.valueOf(dtstart);
2767ae4f20e120d3107cef20be860a612c9c23816295Erik                    newData[1] = String.valueOf(dtend);
2768ae4f20e120d3107cef20be860a612c9c23816295Erik                    newData[2] = tz;
2769ae4f20e120d3107cef20be860a612c9c23816295Erik                    newData[3] = String.valueOf(id);
27702cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                    db.execSQL("UPDATE Events SET " +
27712cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                            "dtstart2=?, " +
27722cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                            "dtend2=?, " +
27732cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                            "eventTimezone2=? " +
27742cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                            "WHERE _id=?",
2775ae4f20e120d3107cef20be860a612c9c23816295Erik                            newData);
2776ae4f20e120d3107cef20be860a612c9c23816295Erik                }
2777ae4f20e120d3107cef20be860a612c9c23816295Erik            } finally {
2778ae4f20e120d3107cef20be860a612c9c23816295Erik                cursor.close();
2779ae4f20e120d3107cef20be860a612c9c23816295Erik            }
2780ae4f20e120d3107cef20be860a612c9c23816295Erik        }
2781ae4f20e120d3107cef20be860a612c9c23816295Erik    }
2782ae4f20e120d3107cef20be860a612c9c23816295Erik
2783ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio    private void upgradeToVersion61(SQLiteDatabase db) {
2784315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        db.execSQL("DROP TABLE IF EXISTS CalendarCache;");
2785315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio
2786315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio        // IF NOT EXISTS should be normal pattern for table creation
27872cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("CREATE TABLE IF NOT EXISTS CalendarCache (" +
27882cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_id INTEGER PRIMARY KEY," +
27892cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "key TEXT NOT NULL," +
27902cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "value TEXT" +
2791315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio                ");");
2792315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio
27932cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("INSERT INTO CalendarCache (" +
27942cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "key, " +
27952cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "value) VALUES (" +
27962cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "'timezoneDatabaseVersion',"  +
27972cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "'2009s'" +
2798315d9326acd39566959f3c547225483f1fb6aefcFabrice Di Meglio                ");");
2799ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio    }
2800ae270e35e14b5c7a756050cb8dcccf5771743850Fabrice Di Meglio
2801ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff    private void upgradeToVersion60(SQLiteDatabase db) {
2802ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        // Switch to CalendarProvider2
2803d5aa3cc17ecda3d72882d9a2e6c48577892df903Ken Shirriff        upgradeSyncState(db);
2804ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        db.execSQL("DROP TRIGGER IF EXISTS calendar_cleanup");
28052cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("CREATE TRIGGER calendar_cleanup DELETE ON Calendars " +
2806ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff                "BEGIN " +
28072cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                ("DELETE FROM Events" +
28082cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                        " WHERE calendar_id=old._id;") +
2809ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff                "END");
28102cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("ALTER TABLE Events" +
28112cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                " ADD COLUMN deleted INTEGER NOT NULL DEFAULT 0;");
2812ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        db.execSQL("DROP TRIGGER IF EXISTS events_insert");
28137cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio        // Trigger to set event's sync_account
28142cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("CREATE TRIGGER events_insert AFTER INSERT ON Events " +
2815ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff                "BEGIN " +
28162cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "UPDATE Events" +
28172cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                " SET _sync_account=" +
28182cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                " (SELECT _sync_account FROM Calendars" +
28192cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                " WHERE Calendars._id=new.calendar_id)," +
28202cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_account_type=" +
28212cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                " (SELECT _sync_account_type FROM Calendars" +
28222cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                " WHERE Calendars._id=new.calendar_id) " +
28232cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "WHERE Events._id=new._id;" +
2824ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff                "END");
2825ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        db.execSQL("DROP TABLE IF EXISTS DeletedEvents;");
2826ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        db.execSQL("DROP TRIGGER IF EXISTS events_cleanup_delete");
28277cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio        // Trigger to remove data tied to an event when we delete that event.
28282cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("CREATE TRIGGER events_cleanup_delete DELETE ON Events " +
2829ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff                "BEGIN " +
28302cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                ("DELETE FROM Instances" +
28312cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                    " WHERE event_id=old._id;" +
28322cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "DELETE FROM EventsRawTimes" +
28332cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                    " WHERE event_id=old._id;" +
28342cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "DELETE FROM Attendees" +
28352cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                    " WHERE event_id=old._id;" +
28362cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "DELETE FROM Reminders" +
28372cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                    " WHERE event_id=old._id;" +
28382cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "DELETE FROM CalendarAlerts" +
28392cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                    " WHERE event_id=old._id;" +
28402cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "DELETE FROM ExtendedProperties" +
28412cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                    " WHERE event_id=old._id;") +
2842ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff                "END");
2843ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        db.execSQL("DROP TRIGGER IF EXISTS attendees_update");
2844ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        db.execSQL("DROP TRIGGER IF EXISTS attendees_insert");
2845ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        db.execSQL("DROP TRIGGER IF EXISTS attendees_delete");
2846ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        db.execSQL("DROP TRIGGER IF EXISTS reminders_update");
2847ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        db.execSQL("DROP TRIGGER IF EXISTS reminders_insert");
2848ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        db.execSQL("DROP TRIGGER IF EXISTS reminders_delete");
2849ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        db.execSQL("DROP TRIGGER IF EXISTS extended_properties_update");
2850ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        db.execSQL("DROP TRIGGER IF EXISTS extended_properties_insert");
2851ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        db.execSQL("DROP TRIGGER IF EXISTS extended_properties_delete");
2852ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff    }
2853ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff
2854ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff    private void upgradeToVersion59(SQLiteDatabase db) {
2855ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        db.execSQL("DROP TABLE IF EXISTS BusyBits;");
28562cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("CREATE TEMPORARY TABLE CalendarMetaData_Backup(" +
28572cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_id," +
28582cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "localTimezone," +
28592cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "minInstance," +
28602cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "maxInstance" +
28617cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                ");");
28622cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("INSERT INTO CalendarMetaData_Backup " +
28637cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                "SELECT " +
28642cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_id," +
28652cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "localTimezone," +
28662cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "minInstance," +
28672cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "maxInstance" +
28682cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                " FROM CalendarMetaData;");
28692cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("DROP TABLE CalendarMetaData;");
28702cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        createCalendarMetaDataTable59(db);
28712cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("INSERT INTO CalendarMetaData " +
28727cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                "SELECT " +
28732cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_id," +
28742cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "localTimezone," +
28752cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "minInstance," +
28762cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "maxInstance" +
28772cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                " FROM CalendarMetaData_Backup;");
28782cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("DROP TABLE CalendarMetaData_Backup;");
2879ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff    }
2880ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff
2881ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff    private void upgradeToVersion57(SQLiteDatabase db) {
28822cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("ALTER TABLE Events" +
28832cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                " ADD COLUMN guestsCanModify" +
28847cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                " INTEGER NOT NULL DEFAULT 0;");
28852cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("ALTER TABLE Events" +
28862cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                " ADD COLUMN guestsCanInviteOthers" +
28877cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                " INTEGER NOT NULL DEFAULT 1;");
28882cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("ALTER TABLE Events" +
28892cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                " ADD COLUMN guestsCanSeeGuests" +
28907cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                " INTEGER NOT NULL DEFAULT 1;");
28912cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("ALTER TABLE Events" +
28922cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                " ADD COLUMN organizer" +
28937cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                " STRING;");
28942cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("UPDATE Events SET organizer=" +
28952cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "(SELECT attendeeEmail" +
28962cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                " FROM Attendees"  +
28977cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                " WHERE " +
28982cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "Attendees.event_id=" +
28992cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "Events._id" +
29007cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                " AND " +
29012cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "Attendees.attendeeRelationship=2);");
2902ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff    }
2903ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff
29041599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio    private void upgradeToVersion56(SQLiteDatabase db) {
29052cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("ALTER TABLE Calendars" +
29062cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                " ADD COLUMN ownerAccount TEXT;");
29072cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("ALTER TABLE Events" +
2908d5f4742d7ba16d791edd9fd33a1a2a42eeac709bRoboErik                " ADD COLUMN hasAttendeeData INTEGER NOT NULL DEFAULT 0;");
29097cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio
29101599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio        // Clear _sync_dirty to avoid a client-to-server sync that could blow away
29111599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio        // server attendees.
29121599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio        // Clear _sync_version to pull down the server's event (with attendees)
29131599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio        // Change the URLs from full-selfattendance to full
29142cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("UPDATE Events"
29152cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                + " SET _sync_dirty=0, "
29162cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                + "_sync_version=NULL, "
29172cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                + "_sync_id="
29182cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                + "REPLACE(_sync_id, " +
29197cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                    "'/private/full-selfattendance', '/private/full'),"
29202cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                + "commentsUri="
29212cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                + "REPLACE(commentsUri, " +
29227cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                    "'/private/full-selfattendance', '/private/full');");
29237cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio
29242cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("UPDATE Calendars"
29252cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                + " SET url="
29262cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                + "REPLACE(url, '/private/full-selfattendance', '/private/full');");
29271599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio
29281599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio        // "cursor" iterates over all the calendars
29292cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        Cursor cursor = db.rawQuery("SELECT _id, " +
29302cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "url FROM Calendars",
29311599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio                null /* selection args */);
29321599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio        // Add the owner column.
29331599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio        if (cursor != null) {
29341599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio            try {
29352cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                final String updateSql = "UPDATE Calendars" +
29362cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                        " SET ownerAccount=?" +
29372cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                        " WHERE _id=?";
29381599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio                while (cursor.moveToNext()) {
29391599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio                    Long id = cursor.getLong(0);
29401599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio                    String url = cursor.getString(1);
29411599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio                    String owner = calendarEmailAddressFromFeedUrl(url);
29427cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                    db.execSQL(updateSql, new Object[] {owner, id});
29431599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio                }
29441599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio            } finally {
29451599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio                cursor.close();
29461599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio            }
29471599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio        }
29481599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio    }
29491599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio
29501599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio    private void upgradeResync(SQLiteDatabase db) {
29511599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio        // Delete sync state, so all records will be re-synced.
29522cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("DELETE FROM _sync_state;");
29531599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio
29541599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio        // "cursor" iterates over all the calendars
29552cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        Cursor cursor = db.rawQuery("SELECT _sync_account," +
29562cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_account_type,url FROM Calendars",
29571599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio                null /* selection args */);
29581599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio        if (cursor != null) {
29591599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio            try {
29601599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio                while (cursor.moveToNext()) {
29611599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio                    String accountName = cursor.getString(0);
29621599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio                    String accountType = cursor.getString(1);
29631599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio                    final Account account = new Account(accountName, accountType);
29641599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio                    String calendarUrl = cursor.getString(2);
29651599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio                    scheduleSync(account, false /* two-way sync */, calendarUrl);
29661599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio                }
29671599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio            } finally {
29681599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio                cursor.close();
29691599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio            }
29701599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio        }
29711599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio    }
29721599ceb270bc70f81dcaf8ecf4568453d7dddd9eFabrice Di Meglio
2973ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff    private void upgradeToVersion55(SQLiteDatabase db) {
29742cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("ALTER TABLE Calendars ADD COLUMN " +
29752cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_account_type TEXT;");
29762cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("ALTER TABLE Events ADD COLUMN " +
29772cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "_sync_account_type TEXT;");
2978ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        db.execSQL("ALTER TABLE DeletedEvents ADD COLUMN _sync_account_type TEXT;");
29792cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("UPDATE Calendars"
29802cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                + " SET _sync_account_type='com.google'"
29812cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                + " WHERE _sync_account IS NOT NULL");
29822cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("UPDATE Events"
29832cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                + " SET _sync_account_type='com.google'"
29842cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                + " WHERE _sync_account IS NOT NULL");
2985ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        db.execSQL("UPDATE DeletedEvents"
2986ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff                + " SET _sync_account_type='com.google'"
2987ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff                + " WHERE _sync_account IS NOT NULL");
2988ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        Log.w(TAG, "re-creating eventSyncAccountAndIdIndex");
2989ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        db.execSQL("DROP INDEX eventSyncAccountAndIdIndex");
29902cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("CREATE INDEX eventSyncAccountAndIdIndex ON Events ("
29912cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                + "_sync_account_type, "
29922cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                + "_sync_account, "
29932cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                + "_sync_id);");
2994ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff    }
2995ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff
2996ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff    private void upgradeToVersion54(SQLiteDatabase db) {
2997ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        Log.w(TAG, "adding eventSyncAccountAndIdIndex");
2998ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        db.execSQL("CREATE INDEX eventSyncAccountAndIdIndex ON Events ("
29992cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                + "_sync_account, _sync_id);");
3000ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff    }
3001ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff
3002ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff    private void upgradeToVersion53(SQLiteDatabase db) {
3003ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        Log.w(TAG, "Upgrading CalendarAlerts table");
30042cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("ALTER TABLE CalendarAlerts ADD COLUMN " +
3005d5f4742d7ba16d791edd9fd33a1a2a42eeac709bRoboErik                "creationTime INTEGER NOT NULL DEFAULT 0;");
30062cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("ALTER TABLE CalendarAlerts ADD COLUMN " +
3007d5f4742d7ba16d791edd9fd33a1a2a42eeac709bRoboErik                "receivedTime INTEGER NOT NULL DEFAULT 0;");
30082cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("ALTER TABLE CalendarAlerts ADD COLUMN " +
3009d5f4742d7ba16d791edd9fd33a1a2a42eeac709bRoboErik                "notifyTime INTEGER NOT NULL DEFAULT 0;");
3010ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff    }
3011ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff
3012ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff    private void upgradeToVersion52(SQLiteDatabase db) {
3013ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        // We added "originalAllDay" to the Events table to keep track of
3014ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        // the allDay status of the original recurring event for entries
3015ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        // that are exceptions to that recurring event.  We need this so
3016ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        // that we can format the date correctly for the "originalInstanceTime"
3017ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        // column when we make a change to the recurrence exception and
3018ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        // send it to the server.
30192cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("ALTER TABLE Events ADD COLUMN " +
30202cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "originalAllDay INTEGER;");
3021ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff
3022ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        // Iterate through the Events table and for each recurrence
3023ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        // exception, fill in the correct value for "originalAllDay",
3024ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        // if possible.  The only times where this might not be possible
3025ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        // are (1) the original recurring event no longer exists, or
3026ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        // (2) the original recurring event does not yet have a _sync_id
3027ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        // because it was created on the phone and hasn't been synced to the
3028ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        // server yet.  In both cases the originalAllDay field will be set
3029ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        // to null.  In the first case we don't care because the recurrence
3030ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        // exception will not be displayed and we won't be able to make
3031ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        // any changes to it (and even if we did, the server should ignore
3032ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        // them, right?).  In the second case, the calendar client already
3033ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        // disallows making changes to an instance of a recurring event
3034ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        // until the recurring event has been synced to the server so the
3035ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        // second case should never occur.
3036ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff
3037ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        // "cursor" iterates over all the recurrences exceptions.
30382cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        Cursor cursor = db.rawQuery("SELECT _id," +
30392cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "originalEvent" +
30402cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                " FROM Events" +
30412cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                " WHERE originalEvent IS NOT NULL",
30427cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                null /* selection args */);
3043ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        if (cursor != null) {
3044ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff            try {
3045ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff                while (cursor.moveToNext()) {
3046ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff                    long id = cursor.getLong(0);
3047ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff                    String originalEvent = cursor.getString(1);
3048ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff
3049ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff                    // Find the original recurring event (if it exists)
30502cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                    Cursor recur = db.rawQuery("SELECT allDay" +
30512cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                            " FROM Events" +
30522cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                            " WHERE _sync_id=?",
30537cb72fa3ea680dce378d8dac71f878e52e03f83aFabrice Di Meglio                            new String[] {originalEvent});
3054ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff                    if (recur == null) {
3055ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff                        continue;
3056ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff                    }
3057ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff
3058ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff                    try {
3059ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff                        // Fill in the "originalAllDay" field of the
3060ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff                        // recurrence exception with the "allDay" value
3061ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff                        // from the recurring event.
3062ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff                        if (recur.moveToNext()) {
3063ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff                            int allDay = recur.getInt(0);
30642cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                            db.execSQL("UPDATE Events" +
30652cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                                    " SET originalAllDay=" + allDay +
30662cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                                    " WHERE _id="+id);
3067ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff                        }
3068ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff                    } finally {
3069ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff                        recur.close();
3070ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff                    }
3071ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff                }
3072ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff            } finally {
3073ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff                cursor.close();
3074ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff            }
30759f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
30769f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
30779f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
3078ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff    private void upgradeToVersion51(SQLiteDatabase db) {
3079ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        Log.w(TAG, "Upgrading DeletedEvents table");
3080ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff
3081ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        // We don't have enough information to fill in the correct
3082ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        // value of the calendar_id for old rows in the DeletedEvents
3083ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        // table, but rows in that table are transient so it is unlikely
3084ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        // that there are any rows.  Plus, the calendar_id is used only
3085ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        // when deleting a calendar, which is a rare event.  All new rows
3086ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        // will have the correct calendar_id.
3087ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        db.execSQL("ALTER TABLE DeletedEvents ADD COLUMN calendar_id INTEGER;");
3088ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff
3089ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        // Trigger to remove a calendar's events when we delete the calendar
3090ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        db.execSQL("DROP TRIGGER IF EXISTS calendar_cleanup");
30912cff10f1a005bd7302245d4c680cf851193c3a97RoboErik        db.execSQL("CREATE TRIGGER calendar_cleanup DELETE ON Calendars " +
3092ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff                "BEGIN " +
30932cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                "DELETE FROM Events WHERE calendar_id=" +
30942cff10f1a005bd7302245d4c680cf851193c3a97RoboErik                    "old._id;" +
3095ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff                "DELETE FROM DeletedEvents WHERE calendar_id = old._id;" +
3096ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff                "END");
3097ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff        db.execSQL("DROP TRIGGER IF EXISTS event_to_deleted");
3098ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff    }
3099ad37c99d051aa4e2508b940c8dec91ee87f53056Ken Shirriff
31009f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    private void dropTables(SQLiteDatabase db) {
31010d8699eedb0f3bcec1854b9753ae59154a122726Michael Chan        Log.i(TAG, "Clearing database");
31020d8699eedb0f3bcec1854b9753ae59154a122726Michael Chan
31030d8699eedb0f3bcec1854b9753ae59154a122726Michael Chan        String[] columns = {
31040d8699eedb0f3bcec1854b9753ae59154a122726Michael Chan                "type", "name"
31050d8699eedb0f3bcec1854b9753ae59154a122726Michael Chan        };
31060d8699eedb0f3bcec1854b9753ae59154a122726Michael Chan        Cursor cursor = db.query("sqlite_master", columns, null, null, null, null, null);
31070d8699eedb0f3bcec1854b9753ae59154a122726Michael Chan        if (cursor == null) {
31080d8699eedb0f3bcec1854b9753ae59154a122726Michael Chan            return;
31090d8699eedb0f3bcec1854b9753ae59154a122726Michael Chan        }
31100d8699eedb0f3bcec1854b9753ae59154a122726Michael Chan        try {
31110d8699eedb0f3bcec1854b9753ae59154a122726Michael Chan            while (cursor.moveToNext()) {
31120d8699eedb0f3bcec1854b9753ae59154a122726Michael Chan                final String name = cursor.getString(1);
31130d8699eedb0f3bcec1854b9753ae59154a122726Michael Chan                if (!name.startsWith("sqlite_")) {
31140d8699eedb0f3bcec1854b9753ae59154a122726Michael Chan                    // If it's not a SQL-controlled entity, drop it
31150d8699eedb0f3bcec1854b9753ae59154a122726Michael Chan                    final String sql = "DROP " + cursor.getString(0) + " IF EXISTS " + name;
31160d8699eedb0f3bcec1854b9753ae59154a122726Michael Chan                    try {
31170d8699eedb0f3bcec1854b9753ae59154a122726Michael Chan                        db.execSQL(sql);
31180d8699eedb0f3bcec1854b9753ae59154a122726Michael Chan                    } catch (SQLException e) {
31190d8699eedb0f3bcec1854b9753ae59154a122726Michael Chan                        Log.e(TAG, "Error executing " + sql + " " + e.toString());
31200d8699eedb0f3bcec1854b9753ae59154a122726Michael Chan                    }
31210d8699eedb0f3bcec1854b9753ae59154a122726Michael Chan                }
31220d8699eedb0f3bcec1854b9753ae59154a122726Michael Chan            }
31230d8699eedb0f3bcec1854b9753ae59154a122726Michael Chan        } finally {
31240d8699eedb0f3bcec1854b9753ae59154a122726Michael Chan            cursor.close();
31250d8699eedb0f3bcec1854b9753ae59154a122726Michael Chan        }
31269f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
31279f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
31289f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    @Override
31299f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    public synchronized SQLiteDatabase getWritableDatabase() {
31309f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        SQLiteDatabase db = super.getWritableDatabase();
31319f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        return db;
31329f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
31339f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
31349f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    public SyncStateContentProviderHelper getSyncState() {
31359f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        return mSyncState;
31369f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
31379f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
31389f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    /**
31399f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * Schedule a calendar sync for the account.
31409f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * @param account the account for which to schedule a sync
31419f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     * @param uploadChangesOnly if set, specify that the sync should only send
31427e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff     *   up local changes.  This is typically used for a local sync, a user override of
31437e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff     *   too many deletions, or a sync after a calendar is unselected.
31447e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff     * @param url the url feed for the calendar to sync (may be null, in which case a poll of
31457e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff     *   all feeds is done.)
31469f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff     */
31479f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    void scheduleSync(Account account, boolean uploadChangesOnly, String url) {
31489f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        Bundle extras = new Bundle();
31497e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        if (uploadChangesOnly) {
31507e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff            extras.putBoolean(ContentResolver.SYNC_EXTRAS_UPLOAD, uploadChangesOnly);
31517e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        }
31529f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        if (url != null) {
31539f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff            extras.putString("feed", url);
31549f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff        }
3155c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert        ContentResolver.requestSync(account, Calendars.CONTENT_URI.getAuthority(),
3156b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                extras);
31579f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff    }
31589f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff
31597e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff    private static void createEventsView(SQLiteDatabase db) {
31607e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        db.execSQL("DROP VIEW IF EXISTS " + Views.EVENTS + ";");
31617e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        String eventsSelect = "SELECT "
3162b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + Tables.EVENTS + "." + CalendarContract.Events._ID
3163b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                        + " AS " + CalendarContract.Events._ID + ","
3164b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Events.TITLE + ","
3165b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Events.DESCRIPTION + ","
3166b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Events.EVENT_LOCATION + ","
3167b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Events.EVENT_COLOR + ","
3168387535fec9f646e0b7acb82d5354f2b5ebee4395RoboErik                + CalendarContract.Events.EVENT_COLOR_KEY + ","
3169b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Events.STATUS + ","
3170b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Events.SELF_ATTENDEE_STATUS + ","
3171b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Events.DTSTART + ","
3172b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Events.DTEND + ","
3173b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Events.DURATION + ","
3174b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Events.EVENT_TIMEZONE + ","
3175b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Events.EVENT_END_TIMEZONE + ","
3176b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Events.ALL_DAY + ","
3177b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Events.ACCESS_LEVEL + ","
3178b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Events.AVAILABILITY + ","
3179b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Events.HAS_ALARM + ","
3180b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Events.HAS_EXTENDED_PROPERTIES + ","
3181b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Events.RRULE + ","
3182b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Events.RDATE + ","
3183b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Events.EXRULE + ","
3184b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Events.EXDATE + ","
3185b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Events.ORIGINAL_SYNC_ID + ","
3186b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Events.ORIGINAL_ID + ","
3187b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Events.ORIGINAL_INSTANCE_TIME + ","
3188b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Events.ORIGINAL_ALL_DAY + ","
3189b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Events.LAST_DATE + ","
3190b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Events.HAS_ATTENDEE_DATA + ","
3191b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Events.CALENDAR_ID + ","
3192b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Events.GUESTS_CAN_INVITE_OTHERS + ","
3193b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Events.GUESTS_CAN_MODIFY + ","
3194b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Events.GUESTS_CAN_SEE_GUESTS + ","
3195b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Events.ORGANIZER + ","
3196b2695bf3cfb173c4c5ba7bfd3c93ba8a51d65810Alon Albert                + "COALESCE("
3197b2695bf3cfb173c4c5ba7bfd3c93ba8a51d65810Alon Albert                + Events.IS_ORGANIZER + ", " + Events.ORGANIZER + " = " + Calendars.OWNER_ACCOUNT
3198b2695bf3cfb173c4c5ba7bfd3c93ba8a51d65810Alon Albert                + ") AS " + Events.IS_ORGANIZER + ","
3199c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan                + CalendarContract.Events.CUSTOM_APP_PACKAGE + ","
3200c81732aeadada8f8bc4c216a317ba458374af2c9Michael Chan                + CalendarContract.Events.CUSTOM_APP_URI + ","
3201501e60bcb1b519d80723f7b64ba60bd079b8ec8dSara Ting                + CalendarContract.Events.UID_2445 + ","
3202b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Events.SYNC_DATA1 + ","
3203b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Events.SYNC_DATA2 + ","
3204b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Events.SYNC_DATA3 + ","
3205b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Events.SYNC_DATA4 + ","
3206b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Events.SYNC_DATA5 + ","
3207b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Events.SYNC_DATA6 + ","
3208b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Events.SYNC_DATA7 + ","
3209b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Events.SYNC_DATA8 + ","
3210b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Events.SYNC_DATA9 + ","
3211b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Events.SYNC_DATA10 + ","
3212b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + Tables.EVENTS + "." + CalendarContract.Events.DELETED
3213b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + " AS " + CalendarContract.Events.DELETED + ","
3214b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + Tables.EVENTS + "." + CalendarContract.Events._SYNC_ID
3215b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + " AS " + CalendarContract.Events._SYNC_ID + ","
3216b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + Tables.EVENTS + "." + CalendarContract.Events.DIRTY
3217b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + " AS " + CalendarContract.Events.DIRTY + ","
32187a2531a4b68e9efe14353cc7f4a64a8c5613e5d3Alon Albert                + Tables.EVENTS + "." + Events.MUTATORS
32197a2531a4b68e9efe14353cc7f4a64a8c5613e5d3Alon Albert                + " AS " + Events.MUTATORS + ","
3220b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + CalendarContract.Events.LAST_SYNCED + ","
3221c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                + Tables.CALENDARS + "." + Calendars.ACCOUNT_NAME
3222b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + " AS " + CalendarContract.Events.ACCOUNT_NAME + ","
3223c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                + Tables.CALENDARS + "." + Calendars.ACCOUNT_TYPE
3224b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + " AS " + CalendarContract.Events.ACCOUNT_TYPE + ","
3225c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                + Calendars.CALENDAR_TIME_ZONE + ","
3226c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                + Calendars.CALENDAR_DISPLAY_NAME + ","
3227c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                + Calendars.CALENDAR_LOCATION + ","
3228c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                + Calendars.VISIBLE + ","
3229c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                + Calendars.CALENDAR_COLOR + ","
3230c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                + Calendars.CALENDAR_COLOR_KEY + ","
3231c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                + Calendars.CALENDAR_ACCESS_LEVEL + ","
3232c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                + Calendars.MAX_REMINDERS + ","
3233c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                + Calendars.ALLOWED_REMINDERS + ","
3234c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                + Calendars.ALLOWED_ATTENDEE_TYPES + ","
3235c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                + Calendars.ALLOWED_AVAILABILITY + ","
3236c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                + Calendars.CAN_ORGANIZER_RESPOND + ","
3237c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                + Calendars.CAN_MODIFY_TIME_ZONE + ","
3238c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                + Calendars.CAN_PARTIALLY_UPDATE + ","
3239c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                + Calendars.CAL_SYNC1 + ","
3240c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                + Calendars.CAL_SYNC2 + ","
3241c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                + Calendars.CAL_SYNC3 + ","
3242c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                + Calendars.CAL_SYNC4 + ","
3243c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                + Calendars.CAL_SYNC5 + ","
3244c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                + Calendars.CAL_SYNC6 + ","
3245c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                + Calendars.CAL_SYNC7 + ","
3246c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                + Calendars.CAL_SYNC8 + ","
3247c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                + Calendars.CAL_SYNC9 + ","
3248c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                + Calendars.CAL_SYNC10 + ","
3249c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                + Calendars.OWNER_ACCOUNT + ","
3250c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                + Calendars.SYNC_EVENTS  + ","
3251c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                + "ifnull(" + Events.EVENT_COLOR + "," + Calendars.CALENDAR_COLOR + ") AS "
3252c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                + Events.DISPLAY_COLOR
32537e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff                + " FROM " + Tables.EVENTS + " JOIN " + Tables.CALENDARS
3254c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                + " ON (" + Tables.EVENTS + "." + Events.CALENDAR_ID
3255c339afc7df041ebfc5f4587f78cf38562aa23459Alon Albert                + "=" + Tables.CALENDARS + "." + Calendars._ID
32567e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff                + ")";
32577e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff
32587e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff        db.execSQL("CREATE VIEW " + Views.EVENTS + " AS " + eventsSelect);
32597e3ec5f2025164fca508f81a5a01940bc912e064Ken Shirriff    }
3260d39cfe09aa7e752cdc7512ae58d90d49d4b5ef9eKen Shirriff
3261d39cfe09aa7e752cdc7512ae58d90d49d4b5ef9eKen Shirriff    /**
3262d39cfe09aa7e752cdc7512ae58d90d49d4b5ef9eKen Shirriff     * Extracts the calendar email from a calendar feed url.
3263d39cfe09aa7e752cdc7512ae58d90d49d4b5ef9eKen Shirriff     * @param feed the calendar feed url
3264d39cfe09aa7e752cdc7512ae58d90d49d4b5ef9eKen Shirriff     * @return the calendar email that is in the feed url or null if it can't
3265d39cfe09aa7e752cdc7512ae58d90d49d4b5ef9eKen Shirriff     * find the email address.
3266d39cfe09aa7e752cdc7512ae58d90d49d4b5ef9eKen Shirriff     * TODO: this is duplicated in CalendarSyncAdapter; move to a library
3267d39cfe09aa7e752cdc7512ae58d90d49d4b5ef9eKen Shirriff     */
3268d39cfe09aa7e752cdc7512ae58d90d49d4b5ef9eKen Shirriff    public static String calendarEmailAddressFromFeedUrl(String feed) {
3269d39cfe09aa7e752cdc7512ae58d90d49d4b5ef9eKen Shirriff        // Example feed url:
3270d39cfe09aa7e752cdc7512ae58d90d49d4b5ef9eKen Shirriff        // https://www.google.com/calendar/feeds/foo%40gmail.com/private/full-noattendees
3271d39cfe09aa7e752cdc7512ae58d90d49d4b5ef9eKen Shirriff        String[] pathComponents = feed.split("/");
3272d39cfe09aa7e752cdc7512ae58d90d49d4b5ef9eKen Shirriff        if (pathComponents.length > 5 && "feeds".equals(pathComponents[4])) {
3273d39cfe09aa7e752cdc7512ae58d90d49d4b5ef9eKen Shirriff            try {
3274d39cfe09aa7e752cdc7512ae58d90d49d4b5ef9eKen Shirriff                return URLDecoder.decode(pathComponents[5], "UTF-8");
3275d39cfe09aa7e752cdc7512ae58d90d49d4b5ef9eKen Shirriff            } catch (UnsupportedEncodingException e) {
3276d39cfe09aa7e752cdc7512ae58d90d49d4b5ef9eKen Shirriff                Log.e(TAG, "unable to url decode the email address in calendar " + feed);
3277d39cfe09aa7e752cdc7512ae58d90d49d4b5ef9eKen Shirriff                return null;
3278d39cfe09aa7e752cdc7512ae58d90d49d4b5ef9eKen Shirriff            }
3279d39cfe09aa7e752cdc7512ae58d90d49d4b5ef9eKen Shirriff        }
3280d39cfe09aa7e752cdc7512ae58d90d49d4b5ef9eKen Shirriff
3281d39cfe09aa7e752cdc7512ae58d90d49d4b5ef9eKen Shirriff        Log.e(TAG, "unable to find the email address in calendar " + feed);
3282d39cfe09aa7e752cdc7512ae58d90d49d4b5ef9eKen Shirriff        return null;
3283d39cfe09aa7e752cdc7512ae58d90d49d4b5ef9eKen Shirriff    }
32841b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio
32851b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio    /**
32861b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio     * Get a "allcalendars" url from a "private/full" or "private/free-busy" url
32871b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio     * @param url
32881b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio     * @return the rewritten Url
32891b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio     *
32901b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio     * For example:
32911b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio     *
32921b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio     *      http://www.google.com/calendar/feeds/joe%40joe.com/private/full
32931b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio     *      http://www.google.com/calendar/feeds/joe%40joe.com/private/free-busy
32941b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio     *
32951b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio     * will be rewriten into:
32961b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio     *
32971b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio     *      http://www.google.com/calendar/feeds/default/allcalendars/full/joe%40joe.com
32981b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio     *      http://www.google.com/calendar/feeds/default/allcalendars/full/joe%40joe.com
32991b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio     */
33001b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio    private static String getAllCalendarsUrlFromEventsUrl(String url) {
33011b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio        if (url == null) {
33021b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio            if (Log.isLoggable(TAG, Log.DEBUG)) {
33031b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio                Log.d(TAG, "Cannot get AllCalendars url from a NULL url");
33041b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio            }
33051b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio            return null;
33061b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio        }
33071b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio        if (url.contains("/private/full")) {
33081b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio            return url.replace("/private/full", "").
33091b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio                    replace("/calendar/feeds", "/calendar/feeds/default/allcalendars/full");
33101b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio        }
33111b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio        if (url.contains("/private/free-busy")) {
33121b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio            return url.replace("/private/free-busy", "").
33131b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio                    replace("/calendar/feeds", "/calendar/feeds/default/allcalendars/full");
33141b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio        }
33151b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio        // Just log as we dont recognize the provided Url
33161b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio        if (Log.isLoggable(TAG, Log.DEBUG)) {
33171b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio            Log.d(TAG, "Cannot get AllCalendars url from the following url: " + url);
33181b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio        }
33191b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio        return null;
33201b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio    }
33211b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio
33221b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio    /**
33231b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio     * Get "selfUrl" from "events url"
33241b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio     * @param url the Events url (either "private/full" or "private/free-busy"
33251b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio     * @return the corresponding allcalendar url
33261b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio     */
33271b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio    private static String getSelfUrlFromEventsUrl(String url) {
33281b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio        return rewriteUrlFromHttpToHttps(getAllCalendarsUrlFromEventsUrl(url));
33291b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio    }
33301b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio
33311b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio    /**
33321b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio     * Get "editUrl" from "events url"
33331b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio     * @param url the Events url (either "private/full" or "private/free-busy"
33341b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio     * @return the corresponding allcalendar url
33351b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio     */
33361b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio    private static String getEditUrlFromEventsUrl(String url) {
33371b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio        return rewriteUrlFromHttpToHttps(getAllCalendarsUrlFromEventsUrl(url));
33381b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio    }
33391b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio
33401b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio    /**
33411b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio     * Rewrite the url from "http" to "https" scheme
33421b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio     * @param url the url to rewrite
33431b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio     * @return the rewritten URL
33441b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio     */
33451b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio    private static String rewriteUrlFromHttpToHttps(String url) {
33461b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio        if (url == null) {
33471b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio            if (Log.isLoggable(TAG, Log.DEBUG)) {
33481b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio                Log.d(TAG, "Cannot rewrite a NULL url");
33491b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio            }
33501b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio            return null;
33511b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio        }
33521b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio        if (url.startsWith(SCHEMA_HTTPS)) {
33531b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio            return url;
33541b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio        }
33551b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio        if (!url.startsWith(SCHEMA_HTTP)) {
33561b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio            throw new IllegalArgumentException("invalid url parameter, unknown scheme: " + url);
33571b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio        }
33581b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio        return SCHEMA_HTTPS + url.substring(SCHEMA_HTTP.length());
33591b6beb61ef04c3da6ab0bdf8504ffecea2b9534cFabrice Di Meglio    }
33609ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert
33611c72909abbfe7559bcc880c339399f1eaa0478f3Andy McFadden    /**
33621c72909abbfe7559bcc880c339399f1eaa0478f3Andy McFadden     * Duplicates an event and its associated tables (Attendees, Reminders, ExtendedProperties).
33631c72909abbfe7559bcc880c339399f1eaa0478f3Andy McFadden     * <p>
33641c72909abbfe7559bcc880c339399f1eaa0478f3Andy McFadden     * Does not create a duplicate if the Calendar's "canPartiallyUpdate" is 0 or the Event's
33651c72909abbfe7559bcc880c339399f1eaa0478f3Andy McFadden     * "dirty" is 1 (so we don't create more than one duplicate).
33661c72909abbfe7559bcc880c339399f1eaa0478f3Andy McFadden     *
33671c72909abbfe7559bcc880c339399f1eaa0478f3Andy McFadden     * @param id The _id of the event to duplicate.
33681c72909abbfe7559bcc880c339399f1eaa0478f3Andy McFadden     */
33699ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert    protected void duplicateEvent(final long id) {
33709ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert        final SQLiteDatabase db = getWritableDatabase();
3371d3b51e172bba03af7d2fcc3559cfa73b6ce60095Alon Albert        try {
3372d3b51e172bba03af7d2fcc3559cfa73b6ce60095Alon Albert            final long canPartiallyUpdate = DatabaseUtils.longForQuery(db, "SELECT "
3373d3b51e172bba03af7d2fcc3559cfa73b6ce60095Alon Albert                    + Calendars.CAN_PARTIALLY_UPDATE + " FROM " + Views.EVENTS
3374d3b51e172bba03af7d2fcc3559cfa73b6ce60095Alon Albert                    + " WHERE " + Events._ID + " = ?", new String[] {
3375d3b51e172bba03af7d2fcc3559cfa73b6ce60095Alon Albert                String.valueOf(id)
3376d3b51e172bba03af7d2fcc3559cfa73b6ce60095Alon Albert            });
3377d3b51e172bba03af7d2fcc3559cfa73b6ce60095Alon Albert            if (canPartiallyUpdate == 0) {
3378d3b51e172bba03af7d2fcc3559cfa73b6ce60095Alon Albert                return;
3379d3b51e172bba03af7d2fcc3559cfa73b6ce60095Alon Albert            }
3380d3b51e172bba03af7d2fcc3559cfa73b6ce60095Alon Albert        } catch (SQLiteDoneException e) {
3381d3b51e172bba03af7d2fcc3559cfa73b6ce60095Alon Albert            // b/11392862
3382d3b51e172bba03af7d2fcc3559cfa73b6ce60095Alon Albert            // If no results are returned, this will be thrown. This can happen if the Events View
3383d3b51e172bba03af7d2fcc3559cfa73b6ce60095Alon Albert            // has no rows for the provided id. This might happen for example if someone inserts a
3384d3b51e172bba03af7d2fcc3559cfa73b6ce60095Alon Albert            // reminder that refers to a non existent event id.
3385d3b51e172bba03af7d2fcc3559cfa73b6ce60095Alon Albert            // Return without doing anything because there is no event to duplicate.
33869ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert            return;
33879ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert        }
33889ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert
33899ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert        db.execSQL("INSERT INTO " + CalendarDatabaseHelper.Tables.EVENTS
33909ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                + "  (" + LAST_SYNCED_EVENT_COLUMNS + ","
33919ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                +         Events.DIRTY + "," + Events.LAST_SYNCED + ")"
33929ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                + " SELECT " + LAST_SYNCED_EVENT_COLUMNS + ", 0, 1"
33939ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                + " FROM " + Tables.EVENTS
33949ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                + " WHERE "  + Events._ID + " = ? AND " + Events.DIRTY + " = ?",
33959ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                new Object[]{
33969ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                        id,
33979ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                        0, // Events.DIRTY
33989ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                });
33999ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert        final long newId = DatabaseUtils.longForQuery(
34009ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                db, "SELECT CASE changes() WHEN 0 THEN -1 ELSE last_insert_rowid() END", null);
34019ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert        if (newId < 0) {
34029ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert            return;
34039ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert        }
34049ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert
34059ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert        if (Log.isLoggable(TAG, Log.VERBOSE)) {
34069ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert            Log.v(TAG, "Duplicating event " + id + " into new event " + newId);
34079ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert        }
34089ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert
3409bcba82631ab0ee16efe58f0e0b0b9c18d93a6fd2Andy McFadden        copyEventRelatedTables(db, newId, id);
3410bcba82631ab0ee16efe58f0e0b0b9c18d93a6fd2Andy McFadden    }
3411bcba82631ab0ee16efe58f0e0b0b9c18d93a6fd2Andy McFadden
34121c72909abbfe7559bcc880c339399f1eaa0478f3Andy McFadden    /**
34131c72909abbfe7559bcc880c339399f1eaa0478f3Andy McFadden     * Makes a copy of the Attendees, Reminders, and ExtendedProperties rows associated with
34141c72909abbfe7559bcc880c339399f1eaa0478f3Andy McFadden     * a specific event.
34151c72909abbfe7559bcc880c339399f1eaa0478f3Andy McFadden     *
34161c72909abbfe7559bcc880c339399f1eaa0478f3Andy McFadden     * @param db The database.
34171c72909abbfe7559bcc880c339399f1eaa0478f3Andy McFadden     * @param newId The ID of the new event.
34181c72909abbfe7559bcc880c339399f1eaa0478f3Andy McFadden     * @param id The ID of the old event.
34191c72909abbfe7559bcc880c339399f1eaa0478f3Andy McFadden     */
3420bcba82631ab0ee16efe58f0e0b0b9c18d93a6fd2Andy McFadden    static void copyEventRelatedTables(SQLiteDatabase db, long newId, long id) {
34219ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert        db.execSQL("INSERT INTO " + Tables.REMINDERS
3422b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + " ( "  + CalendarContract.Reminders.EVENT_ID + ", "
3423b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                        + LAST_SYNCED_REMINDER_COLUMNS + ") "
34249ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                + "SELECT ?," + LAST_SYNCED_REMINDER_COLUMNS
34259ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                + " FROM " + Tables.REMINDERS
3426b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + " WHERE " + CalendarContract.Reminders.EVENT_ID + " = ?",
34279ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                new Object[] {newId, id});
34289ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert        db.execSQL("INSERT INTO "
34299ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                + Tables.ATTENDEES
3430b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + " (" + CalendarContract.Attendees.EVENT_ID + ","
3431b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                        + LAST_SYNCED_ATTENDEE_COLUMNS + ") "
34329ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                + "SELECT ?," + LAST_SYNCED_ATTENDEE_COLUMNS + " FROM " + Tables.ATTENDEES
3433b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + " WHERE " + CalendarContract.Attendees.EVENT_ID + " = ?",
34349ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                new Object[] {newId, id});
34359ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert        db.execSQL("INSERT INTO " + Tables.EXTENDED_PROPERTIES
3436b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + " (" + CalendarContract.ExtendedProperties.EVENT_ID + ","
34379ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                + LAST_SYNCED_EXTENDED_PROPERTY_COLUMNS + ") "
34389ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                + "SELECT ?, " + LAST_SYNCED_EXTENDED_PROPERTY_COLUMNS
34399ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                + " FROM " + Tables.EXTENDED_PROPERTIES
3440b9644fe24edf9e25f0b21c1394e88d25070e0238RoboErik                + " WHERE " + CalendarContract.ExtendedProperties.EVENT_ID + " = ?",
34419ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                new Object[]{newId, id});
34429ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert    }
34439ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert
34449ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert    protected void removeDuplicateEvent(final long id) {
34459ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert        final SQLiteDatabase db = getWritableDatabase();
34469ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert        final Cursor cursor = db.rawQuery("SELECT " + Events._ID + " FROM " + Tables.EVENTS
34479ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                + " WHERE " + Events._SYNC_ID
34489ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                + " = (SELECT " + Events._SYNC_ID
34499ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                + " FROM " + Tables.EVENTS
34509ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                + " WHERE " + Events._ID + " = ?) "
34519ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                + "AND " + Events.LAST_SYNCED + " = ?",
34529ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                new String[]{
34539ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                        String.valueOf(id),
34549ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                        "1", // Events.LAST_SYNCED
34559ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                });
34569ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert        try {
34579ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert            // there should only be at most one but this can't hurt
34589ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert            if (cursor.moveToNext()) {
34599ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                final long dupId = cursor.getLong(0);
34609ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert
34619ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                if (Log.isLoggable(TAG, Log.VERBOSE)) {
34629ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                    Log.v(TAG, "Removing duplicate event " + dupId + " of original event " + id);
34639ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                }
34649ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                // triggers will clean up related tables.
34659ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert                db.execSQL("DELETE FROM Events WHERE " + Events._ID + " = ?", new Object[]{dupId});
34669ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert            }
34679ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert        } finally {
34689ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert          cursor.close();
34699ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert        }
34709ec70fada3d8f7cf56d6b0d0947823ec5bce572cAlon Albert    }
34719f005e4843925efe4fa8434361c4ad4ad384ed4cKen Shirriff}
3472