@Override
        public void onUpgrade(final SQLiteDatabase db, final int oldVersion, final int newVersion) {
            Log.iForce("[DB] Upgrade database from ver. " + oldVersion + " to ver. " + newVersion + ": start");

            try {
                if (db.isReadOnly()) {
                    return;
                }

                db.beginTransaction();

                if (oldVersion <= 0) { // new table
                    dropDatabase(db);
                    onCreate(db);

                    Log.i("Database structure created.");
                }

                if (oldVersion > 0) {
                    if (oldVersion < 52) { // upgrade to 52
                        try {
                            db.execSQL(dbCreateSearchDestinationHistory);

                            Log.i("Added table " + dbTableSearchDestinationHistory + ".");
                        } catch (final SQLException e) {
                            onUpgradeError(e, 52);
                        }
                    }

                    if (oldVersion < 53) { // upgrade to 53
                        try {
                            db.execSQL("ALTER TABLE " + dbTableCaches + " ADD COLUMN onWatchlist INTEGER");

                            Log.i("Column onWatchlist added to " + dbTableCaches + ".");
                        } catch (final SQLException e) {
                            onUpgradeError(e, 53);
                        }
                    }

                    if (oldVersion < 54) { // update to 54
                        try {
                            db.execSQL(dbCreateLogImages);
                        } catch (final SQLException e) {
                            onUpgradeError(e, 54);
                        }
                    }

                    if (oldVersion < 55) { // update to 55
                        try {
                            db.execSQL("ALTER TABLE " + dbTableCaches + " ADD COLUMN personal_note TEXT");
                        } catch (final SQLException e) {
                            onUpgradeError(e, 55);
                        }
                    }

                    // make all internal attribute names lowercase
                    // @see issue #299
                    if (oldVersion < 56) { // update to 56
                        try {
                            db.execSQL("UPDATE " + dbTableAttributes + " SET attribute = " +
                                    "LOWER(attribute) WHERE attribute LIKE \"%_yes\" " +
                                    "OR  attribute LIKE \"%_no\"");
                        } catch (final SQLException e) {
                            onUpgradeError(e, 56);
                        }
                    }

                    // Create missing indices. See issue #435
                    if (oldVersion < 57) { // update to 57
                        try {
                            db.execSQL("DROP INDEX in_a");
                            db.execSQL("DROP INDEX in_b");
                            db.execSQL("DROP INDEX in_c");
                            db.execSQL("DROP INDEX in_d");
                            db.execSQL("DROP INDEX in_e");
                            db.execSQL("DROP INDEX in_f");
                            createIndices(db, 57);
                        } catch (final SQLException e) {
                            onUpgradeError(e, 57);
                        }
                    }

                    if (oldVersion < 58) { // upgrade to 58
                        try {
                            db.beginTransaction();

                            final String dbTableCachesTemp = dbTableCaches + "_temp";
                            final String dbCreateCachesTemp = ""
                                    + "CREATE TABLE " + dbTableCachesTemp + " ("
                                    + "_id INTEGER PRIMARY KEY AUTOINCREMENT, "
                                    + "updated LONG NOT NULL, "
                                    + "detailed INTEGER NOT NULL DEFAULT 0, "
                                    + "detailedupdate LONG, "
                                    + "visiteddate LONG, "
                                    + "geocode TEXT UNIQUE NOT NULL, "
                                    + "reason INTEGER NOT NULL DEFAULT 0, "
                                    + "cacheid TEXT, "
                                    + "guid TEXT, "
                                    + "type TEXT, "
                                    + "name TEXT, "
                                    + "own INTEGER NOT NULL DEFAULT 0, "
                                    + "owner TEXT, "
                                    + "owner_real TEXT, "
                                    + "hidden LONG, "
                                    + "hint TEXT, "
                                    + "size TEXT, "
                                    + "difficulty FLOAT, "
                                    + "terrain FLOAT, "
                                    + "location TEXT, "
                                    + "direction DOUBLE, "
                                    + "distance DOUBLE, "
                                    + "latitude DOUBLE, "
                                    + "longitude DOUBLE, "
                                    + "reliable_latlon INTEGER, "
                                    + "personal_note TEXT, "
                                    + "shortdesc TEXT, "
                                    + "description TEXT, "
                                    + "favourite_cnt INTEGER, "
                                    + "rating FLOAT, "
                                    + "votes INTEGER, "
                                    + "myvote FLOAT, "
                                    + "disabled INTEGER NOT NULL DEFAULT 0, "
                                    + "archived INTEGER NOT NULL DEFAULT 0, "
                                    + "members INTEGER NOT NULL DEFAULT 0, "
                                    + "found INTEGER NOT NULL DEFAULT 0, "
                                    + "favourite INTEGER NOT NULL DEFAULT 0, "
                                    + "inventorycoins INTEGER DEFAULT 0, "
                                    + "inventorytags INTEGER DEFAULT 0, "
                                    + "inventoryunknown INTEGER DEFAULT 0, "
                                    + "onWatchlist INTEGER DEFAULT 0 "
                                    + "); ";

                            db.execSQL(dbCreateCachesTemp);
                            db.execSQL("INSERT INTO " + dbTableCachesTemp + " SELECT _id,updated,detailed,detailedupdate,visiteddate,geocode,reason,cacheid,guid,type,name,own,owner,owner_real," +
                                    "hidden,hint,size,difficulty,terrain,location,direction,distance,latitude,longitude, 0," +
                                    "personal_note,shortdesc,description,favourite_cnt,rating,votes,myvote,disabled,archived,members,found,favourite,inventorycoins," +
                                    "inventorytags,inventoryunknown,onWatchlist FROM " + dbTableCaches);
                            db.execSQL("DROP TABLE " + dbTableCaches);
                            db.execSQL("ALTER TABLE " + dbTableCachesTemp + " RENAME TO " + dbTableCaches);

                            final String dbTableWaypointsTemp = dbTableWaypoints + "_temp";
                            final String dbCreateWaypointsTemp = ""
                                    + "CREATE TABLE " + dbTableWaypointsTemp + " ("
                                    + "_id INTEGER PRIMARY KEY AUTOINCREMENT, "
                                    + "geocode TEXT NOT NULL, "
                                    + "updated LONG NOT NULL, " // date of save
                                    + "type TEXT NOT NULL DEFAULT 'waypoint', "
                                    + "prefix TEXT, "
                                    + "lookup TEXT, "
                                    + "name TEXT, "
                                    + "latitude DOUBLE, "
                                    + "longitude DOUBLE, "
                                    + "note TEXT "
                                    + "); ";
                            db.execSQL(dbCreateWaypointsTemp);
                            db.execSQL("INSERT INTO " + dbTableWaypointsTemp + " SELECT _id, geocode, updated, type, prefix, lookup, name, latitude, longitude, note FROM " + dbTableWaypoints);
                            db.execSQL("DROP TABLE " + dbTableWaypoints);
                            db.execSQL("ALTER TABLE " + dbTableWaypointsTemp + " RENAME TO " + dbTableWaypoints);

                            createIndices(db, 58);

                            db.setTransactionSuccessful();

                            Log.i("Removed latitude_string and longitude_string columns");
                        } catch (final SQLException e) {
                            onUpgradeError(e, 58);
                        } finally {
                            db.endTransaction();
                        }
                    }

                    if (oldVersion < 59) {
                        try {
                            // Add new indices and remove obsolete cache files
                            createIndices(db, 59);
                            removeObsoleteGeocacheDataDirectories();
                        } catch (final SQLException e) {
                            onUpgradeError(e, 59);
                        }
                    }

                    if (oldVersion < 60) {
                        try {
                            removeSecEmptyDirs();
                        } catch (final SQLException e) {
                            onUpgradeError(e, 60);
                        }
                    }
                    if (oldVersion < 61) {
                        try {
                            db.execSQL("ALTER TABLE " + dbTableLogs + " ADD COLUMN friend INTEGER");
                            db.execSQL("ALTER TABLE " + dbTableCaches + " ADD COLUMN coordsChanged INTEGER DEFAULT 0");
                        } catch (final SQLException e) {
                            onUpgradeError(e, 61);
                        }
                    }
                    // Introduces finalDefined on caches and own on waypoints
                    if (oldVersion < 62) {
                        try {
                            db.execSQL("ALTER TABLE " + dbTableCaches + " ADD COLUMN finalDefined INTEGER DEFAULT 0");
                            db.execSQL("ALTER TABLE " + dbTableWaypoints + " ADD COLUMN own INTEGER DEFAULT 0");
                            db.execSQL("UPDATE " + dbTableWaypoints + " SET own = 1 WHERE type = 'own'");
                        } catch (final SQLException e) {
                            onUpgradeError(e, 62);
                        }
                    }
                    if (oldVersion < 63) {
                        try {
                            removeDoubleUnderscoreMapFiles();
                        } catch (final SQLException e) {
                            onUpgradeError(e, 63);
                        }
                    }

                    if (oldVersion < 64) {
                        try {
                            // No cache should ever be stored into the ALL_CACHES list. Here we use hardcoded list ids
                            // rather than symbolic ones because the fix must be applied with the values at the time
                            // of the problem. The problem was introduced in release 2012.06.01.
                            db.execSQL("UPDATE " + dbTableCaches + " SET reason=1 WHERE reason=2");
                        } catch (final SQLException e) {
                            onUpgradeError(e, 64);
                        }
                    }

                    if (oldVersion < 65) {
                        try {
                            // Set all waypoints where name is Original coordinates to type ORIGINAL
                            db.execSQL("UPDATE " + dbTableWaypoints + " SET type='original', own=0 WHERE name='Original Coordinates'");
                        } catch (final SQLException e) {
                            onUpgradeError(e, 65);
                        }
                    }
                    // Introduces visited feature on waypoints
                    if (oldVersion < 66) {
                        try {
                            db.execSQL("ALTER TABLE " + dbTableWaypoints + " ADD COLUMN visited INTEGER DEFAULT 0");
                        } catch (final SQLException e) {
                            onUpgradeError(e, 66);
                        }
                    }
                    // issue2662 OC: Leichtes Klettern / Easy climbing
                    if (oldVersion < 67) {
                        try {
                            db.execSQL("UPDATE " + dbTableAttributes + " SET attribute = 'easy_climbing_yes' WHERE geocode LIKE 'OC%' AND attribute = 'climbing_yes'");
                            db.execSQL("UPDATE " + dbTableAttributes + " SET attribute = 'easy_climbing_no' WHERE geocode LIKE 'OC%' AND attribute = 'climbing_no'");
                        } catch (final SQLException e) {
                            onUpgradeError(e, 67);
                        }
                    }
                    // Introduces logPasswordRequired on caches
                    if (oldVersion < 68) {
                        try {
                            db.execSQL("ALTER TABLE " + dbTableCaches + " ADD COLUMN logPasswordRequired INTEGER DEFAULT 0");
                        } catch (final SQLException e) {
                            onUpgradeError(e, 68);
                        }
                    }
                    // description for log Images
                    if (oldVersion < 69) {
                        try {
                            db.execSQL("ALTER TABLE " + dbTableLogImages + " ADD COLUMN description TEXT");
                        } catch (final SQLException e) {
                            onUpgradeError(e, 69);
                        }
                    }
                    // Introduces watchListCount
                    if (oldVersion < 70) {
                        try {
                            db.execSQL("ALTER TABLE " + dbTableCaches + " ADD COLUMN watchlistCount INTEGER DEFAULT -1");
                        } catch (final SQLException e) {
                            onUpgradeError(e, 70);
                        }
                    }
                    // Introduces cachesLists
                    if (oldVersion < 71) {
                        try {
                            db.execSQL(dbCreateCachesLists);
                            createIndices(db, 71);
                            db.execSQL("INSERT INTO " + dbTableCachesLists + " SELECT reason, geocode FROM " + dbTableCaches);
                        } catch (final SQLException e) {
                            onUpgradeError(e, 71);
                        }
                    }
                    // User notes in waypoints and local coords changes of WPs without coords on server
                    if (oldVersion < 72) {
                        try {
                            db.execSQL("ALTER TABLE " + dbTableWaypoints + " ADD COLUMN user_note TEXT");
                            db.execSQL("ALTER TABLE " + dbTableWaypoints + " ADD COLUMN org_coords_empty INTEGER DEFAULT 0");
                            db.execSQL("UPDATE " + dbTableWaypoints + " SET user_note = note");
                            db.execSQL("UPDATE " + dbTableWaypoints + " SET note = ''");
                            db.execSQL("UPDATE " + dbTableWaypoints + " SET org_coords_empty = 1 WHERE latitude IS NULL AND longitude IS NULL");
                        } catch (final SQLException e) {
                            onUpgradeError(e, 72);
                        }
                    }
                    // Adds coord calculator state to the waypoint
                    if (oldVersion < 73) {
                        try {
                            db.execSQL("ALTER TABLE " + dbTableWaypoints + " ADD COLUMN calc_state TEXT");
                        } catch (final SQLException e) {
                            onUpgradeError(e, 73);
                        }
                    }

                    // Adds report problem to offline log
                    if (oldVersion < 74) {
                        try {
                            db.execSQL("ALTER TABLE " + dbTableLogsOffline + " ADD COLUMN report_problem TEXT");
                        } catch (final SQLException e) {
                            onUpgradeError(e, 74);
                        }
                    }

                    // Adds log information for trackables
                    if (oldVersion < 75) {
                        try {
                            db.execSQL("ALTER TABLE " + dbTableTrackables + " ADD COLUMN log_date LONG");
                            db.execSQL("ALTER TABLE " + dbTableTrackables + " ADD COLUMN log_type INTEGER");
                            db.execSQL("ALTER TABLE " + dbTableTrackables + " ADD COLUMN log_guid TEXT");
                        } catch (final SQLException e) {
                            onUpgradeError(e, 75);
                        }
                    }

                    // add trail history table
                    if (oldVersion < 76) {
                        try {
                            db.execSQL(dbCreateTrailHistory);

                            Log.i("Added table " + dbTableTrailHistory + ".");
                        } catch (final SQLException e) {
                            onUpgradeError(e, 76);
                        }
                    }

                    // add column for list marker
                    if (oldVersion < 77) {
                        try {
                            db.execSQL("ALTER TABLE " + dbTableLists + " ADD COLUMN marker INTEGER NOT NULL DEFAULT 0");
                        } catch (final SQLException e) {
                            onUpgradeError(e, 77);
                        }
                    }

                    // 78 has been revoked

                    // next one is needed only for users with version 78, therefore using "==" instead of the regular "<"
                    if (oldVersion == 78) {
                        try {
                            db.execSQL("CREATE TABLE IF NOT EXISTS " + dbTableSearchDestinationHistory + " ("
                                    + "_id INTEGER PRIMARY KEY AUTOINCREMENT, "
                                    + "date LONG NOT NULL, "
                                    + "latitude DOUBLE, "
                                    + "longitude DOUBLE "
                                    + ")");
                        } catch (final SQLException e) {
                            onUpgradeError(e, 79);
                        }
                    }

                    if (oldVersion < 80) {
                        try {
                            db.execSQL("ALTER TABLE " + dbTableCaches + " ADD COLUMN preventWaypointsFromNote INTEGER NOT NULL DEFAULT 0");
                        } catch (final SQLException e) {
                            onUpgradeError(e, 80);
                        }
                    }

                    // add route table
                    if (oldVersion < 81) {
                        try {
                            db.execSQL(dbCreateRoute);

                            Log.i("Added table " + dbTableRoute + ".");
                        } catch (final SQLException e) {
                            onUpgradeError(e, 81);
                        }
                    }

                    // add extension table
                    if (oldVersion < 82) {
                        try {
                            db.execSQL(dbCreateExtension);

                            Log.i("Added table " + dbTableExtension + ".");
                        } catch (final SQLException e) {
                            onUpgradeError(e, 82);
                        }
                    }

                    // fix a few creation errors
                    if (oldVersion < 83) {
                        // remove "table" infix for route table by renaming table
                        try {
                            db.execSQL("ALTER TABLE cg_table_route RENAME TO " + dbTableRoute);
                        } catch (final SQLException e) {
                            // ignore, because depending on your upgrade path, the statement above cannot work
                        }
                        // recreate extension table to remove "table" infix and to fix two column types
                        try {
                            db.execSQL("DROP TABLE IF EXISTS cg_table_extension;");
                            db.execSQL("DROP TABLE IF EXISTS cg_extension;");
                            db.execSQL(dbCreateExtension);
                        } catch (final SQLException e) {
                            onUpgradeError(e, 83);
                        }
                    }

                    // redefine & migrate route table
                    if (oldVersion < 84 && oldVersion > 80) {
                        try {
                            db.execSQL("ALTER TABLE " + dbTableRoute + " RENAME TO temp_route");
                            db.execSQL(dbCreateRoute);
                            // migrate existing caches in individual route
                            db.execSQL("INSERT INTO " + dbTableRoute + " (precedence, type, id, latitude, longitude)"
                                    + " SELECT precedence, " + RouteItem.RouteItemType.GEOCACHE.ordinal() + " type, geocode id, latitude, longitude"
                                    + " FROM temp_route LEFT JOIN " + dbTableCaches + " USING (geocode)"
                                    + " WHERE temp_route.type=1");
                            // migrate existing waypoints in individual route
                            db.execSQL("INSERT INTO " + dbTableRoute + " (precedence, type, id, latitude, longitude)"
                                    + " SELECT precedence, " + RouteItem.RouteItemType.WAYPOINT.ordinal() + " type, " + dbTableWaypoints + ".geocode || \"-\" || PREFIX id, latitude, longitude"
                                    + " FROM temp_route INNER JOIN " + dbTableWaypoints + " ON (temp_route.id = " + dbTableWaypoints + "._id)"
                                    + " WHERE temp_route.type=0");
                            // drop temp table
                            db.execSQL("DROP TABLE IF EXISTS temp_route");
                        } catch (final SQLException e) {
                            onUpgradeError(e, 84);
                        }
                    }

                    //enhance offline logging storage
                    if (oldVersion < 85) {
                        try {
                            //add new columns
                            createColumnIfNotExists(db, dbTableLogsOffline, "image_title_prefix TEXT");
                            createColumnIfNotExists(db, dbTableLogsOffline, "image_scale INTEGER");
                            createColumnIfNotExists(db, dbTableLogsOffline, "favorite INTEGER");
                            createColumnIfNotExists(db, dbTableLogsOffline, "rating FLOAT");
                            createColumnIfNotExists(db, dbTableLogsOffline, "password TEXT");
                            createColumnIfNotExists(db, dbTableLogsOffline, "tweet INTEGER"); // no longer used
                            //add new tables
                            db.execSQL("DROP TABLE IF EXISTS " + dbTableLogsOfflineImages);
                            db.execSQL("DROP TABLE IF EXISTS " + dbTableLogsOfflineTrackables);
                            db.execSQL(dbCreateLogsOfflineImages);
                            db.execSQL(dbCreateLogsOfflineTrackables);
                        } catch (final SQLException e) {
                            onUpgradeError(e, 85);
                        }
                    }

                    //(re)create indices for logging tables
                    if (oldVersion < 86) {
                        db.execSQL("DROP INDEX in_logs_geo");
                        createIndices(db, 86);
                    }

                    //add service log id
                    if (oldVersion < 87) {
                        try {
                            //add new columns
                            createColumnIfNotExists(db, dbTableLogsOffline, "service_log_id TEXT");
                            createColumnIfNotExists(db, dbTableLogs, "service_log_id TEXT");
                        } catch (final SQLException e) {
                            onUpgradeError(e, 87);
                        }
                    }

                    // add timestamp to cg_trail_history
                    if (oldVersion < 88) {
                        try {
                            createColumnIfNotExists(db, dbTableTrailHistory, "timestamp INTEGER DEFAULT 0");
                            db.execSQL("UPDATE " + dbTableTrailHistory + " SET timestamp =" + System.currentTimeMillis());
                        } catch (final SQLException e) {
                            onUpgradeError(e, 88);
                        }
                    }

                    // add altitude to cg_trail_history
                    if (oldVersion < 89) {
                        try {
                            createColumnIfNotExists(db, dbTableTrailHistory, "altitude DOUBLE DEFAULT 0.0");
                            db.execSQL("UPDATE " + dbTableTrailHistory + " SET altitude = 0.0");
                        } catch (final SQLException e) {
                            onUpgradeError(e, 89);
                        }
                    }

                    // add user guid to cg_caches and cg_logs
                    if (oldVersion < 90) {
                        try {
                            createColumnIfNotExists(db, dbTableCaches, "owner_guid TEXT NOT NULL DEFAULT ''");
                            createColumnIfNotExists(db, dbTableLogs, "author_guid TEXT NOT NULL DEFAULT ''");
                        } catch (final SQLException e) {
                            onUpgradeError(e, 90);
                        }
                    }

                    // add field to cg_extension
                    if (oldVersion < 91) {
                        try {
                            createColumnIfNotExists(db, dbTableExtension, "long3 LONG NOT NULL DEFAULT 0");
                            createColumnIfNotExists(db, dbTableExtension, "long4 LONG NOT NULL DEFAULT 0");
                            createColumnIfNotExists(db, dbTableExtension, "string3 TEXT NOT NULL DEFAULT ''");
                            createColumnIfNotExists(db, dbTableExtension, "string4 TEXT NOT NULL DEFAULT ''");
                        } catch (final SQLException e) {
                            onUpgradeError(e, 91);
                        }
                    }

                    // add emoji to cg_caches
                    if (oldVersion < 92) {
                        try {
                            createColumnIfNotExists(db, dbTableCaches, "emoji INTEGER DEFAULT 0");
                        } catch (final SQLException e) {
                            onUpgradeError(e, 92);
                        }
                    }

                    // add emoji to cg_lists
                    if (oldVersion < 93) {
                        try {
                            createColumnIfNotExists(db, dbTableLists, "emoji INTEGER DEFAULT 0");
                            // migrate marker values
                            db.execSQL("UPDATE " + dbTableLists + " SET emoji = " + 0xe01e + " WHERE marker=1");    // green
                            db.execSQL("UPDATE " + dbTableLists + " SET emoji = " + 0xe030 + " WHERE marker=2");    // orange
                            db.execSQL("UPDATE " + dbTableLists + " SET emoji = " + 0xe01d + " WHERE marker=3");    // blue
                            db.execSQL("UPDATE " + dbTableLists + " SET emoji = " + 0xe024 + " WHERE marker=4");    // red
                            db.execSQL("UPDATE " + dbTableLists + " SET emoji = " + 0xe020 + " WHERE marker=5");    // turquoise
                            db.execSQL("UPDATE " + dbTableLists + " SET emoji = " + 0xe043 + " WHERE marker=6");    // black
                            // do not remove old field "marker" to keep db structure backward-compatible
                        } catch (final SQLException e) {
                            onUpgradeError(e, 93);
                        }
                    }

                    //add scale to offline log image
                    if (oldVersion < 94) {
                        try {
                            createColumnIfNotExists(db, dbTableLogsOfflineImages, "scale INTEGER");

                        } catch (final SQLException e) {
                            onUpgradeError(e, 94);
                        }
                    }

                    //add table to store custom filters
                    if (oldVersion < 95) {
                        try {
                            db.execSQL(dbCreateFilters);
                        } catch (final SQLException e) {
                            onUpgradeError(e, 95);
                        }
                    }

                    //add preventAskForDeletion to cg_lists
                    if (oldVersion < 96) {
                        try {
                            createColumnIfNotExists(db, dbTableLists, FIELD_LISTS_PREVENTASKFORDELETION + " INTEGER DEFAULT 0");
                        } catch (final SQLException e) {
                            onUpgradeError(e, 96);
                        }
                    }

                    //rename lab adventure caches geocodes prefix from LC to AL
                    if (oldVersion < 97) {
                        try {
                            final String sql = " SET geocode = \"AL\" || SUBSTR(geocode, 3) WHERE SUBSTR(geocode, 1, 2) = \"LC\" AND LENGTH(geocode) > 10";
                            db.execSQL("UPDATE " + dbTableCaches + sql);
                            db.execSQL("UPDATE " + dbTableAttributes + sql);
                            db.execSQL("UPDATE " + dbTableCachesLists + sql);
                            db.execSQL("UPDATE " + dbTableLogCount + sql);
                            db.execSQL("UPDATE " + dbTableLogs + sql);
                            db.execSQL("UPDATE " + dbTableLogsOffline + sql);
                            db.execSQL("UPDATE " + dbTableSpoilers + sql);
                            db.execSQL("UPDATE " + dbTableTrackables + sql);
                            db.execSQL("UPDATE " + dbTableWaypoints + sql);
                        } catch (final SQLException e) {
                            onUpgradeError(e, 97);
                        }
                    }

                    //create table for variable storage
                    if (oldVersion < 98) {
                        try {
                            db.execSQL(dbCreateVariables);
                            createIndices(db, 98);
                        } catch (final SQLException e) {
                            onUpgradeError(e, 98);
                        }
                    }

                    // add alcMode to cg_caches
                    if (oldVersion < 99) {
                        try {
                            createColumnIfNotExists(db, dbTableCaches, "alcMode INTEGER DEFAULT 0");
                        } catch (final SQLException e) {
                            onUpgradeError(e, 99);
                        }
                    }

                    //create table for category storage
                    if (oldVersion < 100) {
                        try {
                            createColumnIfNotExists(db, dbTableCaches, "tier TEXT");
                            db.execSQL(dbCreateCategories);
                            createIndices(db, 100);
                        } catch (final SQLException e) {
                            onUpgradeError(e, 100);
                        }
                    }

                    //create new column
                    if (oldVersion < 101) {
                        try {
                            createColumnIfNotExists(db, dbTableLogImages, "service_image_id TEXT");
                        } catch (final SQLException e) {
                            onUpgradeError(e, 101);
                        }
                    }

                    // Adds projection attributes to waypoints
                    if (oldVersion < 102) {
                        try {
                            createColumnIfNotExists(db, dbTableWaypoints, "projection_type TEXT");
                            createColumnIfNotExists(db, dbTableWaypoints, "projection_unit TEXT");
                            createColumnIfNotExists(db, dbTableWaypoints, "projection_formula_1 TEXT");
                            createColumnIfNotExists(db, dbTableWaypoints, "projection_formula_2 TEXT");
                        } catch (final SQLException e) {
                            onUpgradeError(e, 102);
                        }
                    }

                    // Adds more projection attributes to waypoints
                    if (oldVersion < 103) {
                        try {
                            createColumnIfNotExists(db, dbTableWaypoints, "preprojected_latitude DOUBLE");
                            createColumnIfNotExists(db, dbTableWaypoints, "preprojected_longitude DOUBLE");
                        } catch (final SQLException e) {
                            onUpgradeError(e, 103);
                        }
                    }

                    // Adds radius for lab stages to caches
                    if (oldVersion < 104) {
                        try {
                            createColumnIfNotExists(db, dbTableWaypoints, "geofence DOUBLE");
                        } catch (final SQLException e) {
                            onUpgradeError(e, 104);
                        }
                    }

                    // Migrate UDC geocodes from ZZ1000-based numbers to random ones
                    if (oldVersion < 105) {
                        try {
                            final String query = "select geocode from cg_caches where geocode >= 'ZZ1000' and geocode < 'ZZ2000'";
                            try (Cursor cursor = db.rawQuery(query, null)) {
                                while (cursor.moveToNext()) {
                                    final String geocode = cursor.getString(0);
                                    final String newGeocode = InternalConnector.PREFIX + InternalConnector.generateRandomId();
                                    for (String table : new String[] { "cg_attributes", "cg_caches",  "cg_caches_lists", "cg_categories", "cg_logCount", "cg_logs", "cg_logs_offline", "cg_spoilers", "cg_variables", "cg_waypoints" }) {
                                        db.execSQL("UPDATE " + table + " SET geocode = '" + newGeocode + "' WHERE geocode = '" + geocode + "'");
                                    }

                                }
                            }
                        } catch (final SQLException e) {
                            onUpgradeError(e, 105);
                        }
                    }

                    // Update lab cache DT values
                    if (oldVersion < 106) {
                        try {
                            db.execSQL("UPDATE " + dbTableCaches + " SET difficulty = 0 WHERE difficulty < 0");
                            db.execSQL("UPDATE " + dbTableCaches + " SET terrain = 0 WHERE terrain < 0");
                        } catch (final SQLException e) {
                            onUpgradeError(e, 106);
                        }
                    }

                }

                //at the very end of onUpgrade: rewrite downgradeable versions in database
                try {
                    DBDowngradeableVersions.save(db, DBVERSIONS_DOWNWARD_COMPATIBLE);
                } catch (final Exception e) {
                    Log.e("Failed to rewrite downgradeable versions to " + DBVERSIONS_DOWNWARD_COMPATIBLE, e);
                }

                db.setTransactionSuccessful();
            } finally {
                db.endTransaction();
            }

            Log.iForce("[DB] Upgrade database from ver. " + oldVersion + " to ver. " + newVersion + ": completed");
        }
We override the default open/create as it doesn't work on OS 1.6 and
causes issues on other devices too.
main/src/main/java/cgeo/geocaching/storage/DataStore.java