From 3240faf7f2c92a2ba4f077b11209107c96cb29bb Mon Sep 17 00:00:00 2001 From: Peter Serwylo Date: Thu, 20 Feb 2014 15:29:50 +1100 Subject: [PATCH] Fix "duplicate column: maxage" (issue #445) The bug is explained in detail in the issue tracker. This change added guard condition to check for existence of the field before adding. While I was at it, I also guarded a bunch of other ALTER statements with the if (!columnExists()) check. It turns out that many of them break, but we only saw the first one because it threw an exception before getting to the others. --- src/org/fdroid/fdroid/data/DBHelper.java | 76 ++++++++++++------------ 1 file changed, 39 insertions(+), 37 deletions(-) diff --git a/src/org/fdroid/fdroid/data/DBHelper.java b/src/org/fdroid/fdroid/data/DBHelper.java index db273fa29..8600e47ce 100644 --- a/src/org/fdroid/fdroid/data/DBHelper.java +++ b/src/org/fdroid/fdroid/data/DBHelper.java @@ -120,49 +120,49 @@ public class DBHelper extends SQLiteOpenHelper { } private void renameRepoId(SQLiteDatabase db, int oldVersion) { - if (oldVersion < 36) { + if (oldVersion < 36 && !columnExists(db, TABLE_REPO, "_id")) { Log.d("FDroid", "Renaming " + TABLE_REPO + ".id to _id"); db.beginTransaction(); try { - // http://stackoverflow.com/questions/805363/how-do-i-rename-a-column-in-a-sqlite-database-table#805508 - String tempTableName = TABLE_REPO + "__temp__"; - db.execSQL("ALTER TABLE " + TABLE_REPO + " RENAME TO " + tempTableName + ";" ); + // http://stackoverflow.com/questions/805363/how-do-i-rename-a-column-in-a-sqlite-database-table#805508 + String tempTableName = TABLE_REPO + "__temp__"; + db.execSQL("ALTER TABLE " + TABLE_REPO + " RENAME TO " + tempTableName + ";" ); - // I realise this is available in the CREATE_TABLE_REPO above, - // however I have a feeling that it will need to be the same as the - // current structure of the table as of DBVersion 36, or else we may - // get into strife. For example, if there was a field that - // got removed, then it will break the "insert select" - // statement. Therefore, I've put a copy of CREATE_TABLE_REPO - // here that is the same as it was at DBVersion 36. - String createTableDdl = "create table " + TABLE_REPO + " (" - + "_id integer not null primary key, " - + "address text not null, " - + "name text, " - + "description text, " - + "inuse integer not null, " - + "priority integer not null, " - + "pubkey text, " - + "fingerprint text, " - + "maxage integer not null default 0, " - + "version integer not null default 0, " - + "lastetag text, " - + "lastUpdated string);"; + // I realise this is available in the CREATE_TABLE_REPO above, + // however I have a feeling that it will need to be the same as the + // current structure of the table as of DBVersion 36, or else we may + // get into strife. For example, if there was a field that + // got removed, then it will break the "insert select" + // statement. Therefore, I've put a copy of CREATE_TABLE_REPO + // here that is the same as it was at DBVersion 36. + String createTableDdl = "create table " + TABLE_REPO + " (" + + "_id integer not null primary key, " + + "address text not null, " + + "name text, " + + "description text, " + + "inuse integer not null, " + + "priority integer not null, " + + "pubkey text, " + + "fingerprint text, " + + "maxage integer not null default 0, " + + "version integer not null default 0, " + + "lastetag text, " + + "lastUpdated string);"; - db.execSQL(createTableDdl); + db.execSQL(createTableDdl); - String nonIdFields = "address, name, description, inuse, priority, " + - "pubkey, fingerprint, maxage, version, lastetag, lastUpdated"; + String nonIdFields = "address, name, description, inuse, priority, " + + "pubkey, fingerprint, maxage, version, lastetag, lastUpdated"; - String insertSql = "INSERT INTO " + TABLE_REPO + - "(_id, " + nonIdFields + " ) " + - "SELECT id, " + nonIdFields + " FROM " + tempTableName + ";"; + String insertSql = "INSERT INTO " + TABLE_REPO + + "(_id, " + nonIdFields + " ) " + + "SELECT id, " + nonIdFields + " FROM " + tempTableName + ";"; - db.execSQL(insertSql); - db.execSQL("DROP TABLE " + tempTableName + ";"); - db.setTransactionSuccessful(); + db.execSQL(insertSql); + db.execSQL("DROP TABLE " + tempTableName + ";"); + db.setTransactionSuccessful(); } catch (Exception e) { Log.e("FDroid", "Error renaming id to _id: " + e.getMessage()); } @@ -273,10 +273,12 @@ public class DBHelper extends SQLiteOpenHelper { * default repos with values from strings.xml. */ private void addNameAndDescriptionToRepo(SQLiteDatabase db, int oldVersion) { - if (oldVersion < 21) { - if (!columnExists(db, TABLE_REPO, "name")) + boolean nameExists = columnExists(db, TABLE_REPO, "name"); + boolean descriptionExists = columnExists(db, TABLE_REPO, "description"); + if (oldVersion < 21 && !(nameExists && descriptionExists)) { + if (!nameExists) db.execSQL("alter table " + TABLE_REPO + " add column name text"); - if (!columnExists(db, TABLE_REPO, "description")) + if (!descriptionExists) db.execSQL("alter table " + TABLE_REPO + " add column description text"); ContentValues values = new ContentValues(); values.put("name", context.getString(R.string.default_repo_name)); @@ -322,7 +324,7 @@ public class DBHelper extends SQLiteOpenHelper { } private void addMaxAgeToRepo(SQLiteDatabase db, int oldVersion) { - if (oldVersion < 30) { + if (oldVersion < 30 && !columnExists(db, TABLE_REPO, "maxage")) { db.execSQL("alter table " + TABLE_REPO + " add column maxage integer not null default 0"); } }