2015-04-11 7 views
2

Я разрабатываю приложение, которое использует ormlite и sqlcipher. Мне нужно, чтобы переименовать столбец, не теряя при этом все его данные. Но после обновления столбца - я не могу использовать метод queryForAll для ormlite. Я попытался найти проблему, но не было никакой удачи. Заранее спасибо.Ormlite после обновленной таблицы Я не могу использовать запрос для всех методов

Вот мой метод обновления таблицы:

List<DB_RecordItem> recordItems; 
    List<JSONObject> objects = new ArrayList<>(); 
    try { 
     // Add new column - file_id (instead of 'file') 
     db.execSQL(String.format("ALTER TABLE %s ADD COLUMN %s INTEGER;", DB_RecordItem.DB_TABLE, DB_File.DB_FILE)); 

     // Get all items, which are going to be stored later. 
     recordItems = Database.getRecordItems().queryForAll(); 

     Dao<DB_RecordItem, String> dao = DaoManager.createDao(connectionSource, DB_RecordItem.class); 
     Log.i("DatabaseLog", "Before delete table: " + dao.queryRaw("PRAGMA table_info(db_recorditem)").getResults().toString()); 

     QueryBuilder<DB_RecordItem, String> qb = dao.queryBuilder(); 

     // Query for all items. 
     for (DB_RecordItem item : recordItems) { 
      JSONObject jsonObject = new JSONObject(item.toJson()); 

      Log.i("DatabaseLog", "Before: " + jsonObject.toString()); 

      qb.where().eq("id", item.getId()); 
      CloseableIterator<DB_RecordItem> iterator = dao.iterator(qb.prepare()); 
      // Get old file id, since model id is changed to "file_id" 
      GenericRawResults<String[]> rawResults = dao.queryRaw("select file from db_recorditem where id = " + item.getId()); 

      try { 
       int file_id = Integer.valueOf(rawResults.getResults().get(0)[0]); 
        if (file_id != -1) { 
         // If file_id it is not -1, then the recrod item had a file_id. 
         jsonObject.put(DB_File.DB_FILE, file_id); 
        } 
      } finally { 
       iterator.closeQuietly(); 
      } 

      // Set all ids to 0, autoincrement will do its thing. 
      jsonObject.remove(DB_Core.DB_ID); 
      jsonObject.put(DB_Core.DB_ID, 0); 
      // Store new data. 
      objects.add(jsonObject); 
     } 

     // Drop old table, with column that we don't need any more. 
     TableUtils.dropTable(connectionSource, DB_RecordItem.class, false); 
     // Create new table with correct column naming. 
     TableUtils.createTable(connectionSource, DB_RecordItem.class); 

     Log.i("DatabaseLog", "New table: " + dao.queryRaw("PRAGMA table_info(db_recorditem)").getResults().toString()); 

     // Store all data. 
     for (JSONObject object : objects) { 
      Log.i("DatabaseLog", "After: " + object.toString()); 
      new DB_RecordItem(object).save(); 
     } 

     Log.i("DatabaseLog", "Done!"); 
    } catch (Exception e) { 
     Log.i("DatabaseLog", "Crash."); 
     e.printStackTrace(); 
    } 

Код выше, кажется, прекрасно работают без каких-либо ошибок. Однако я получаю ошибку после того, как я пытаюсь продолжить эту линию:

// getRecordItems() returns Dao<DB_RecordItem, Integer> 
Database.getRecordItems().queryForAll() 

Оказывается, что проблема с новым insrted поля. Если поля не имеют значения «file_id», все работает нормально. Но если это так - ошибка воспроизводится. Есть ли шанс, что мне нужно восстановить ormlite config_file?

Мое сообщение об ошибке:

E/CursorWindow﹕ Bad request for field slot 0,17. numRows = 1, numColumns = 17 
W/System.err﹕ java.lang.IllegalStateException: get field slot from row 0 col 17 failed 
W/System.err﹕ at net.sqlcipher.CursorWindow.getLong_native(Native Method) 
W/System.err﹕ at net.sqlcipher.CursorWindow.getInt(CursorWindow.java:522) 
W/System.err﹕ at net.sqlcipher.AbstractWindowedCursor.getInt(AbstractWindowedCursor.java:95) 
W/System.err﹕ at android.database.CursorWrapper.getInt(CursorWrapper.java:102) 
W/System.err﹕ at com.j256.ormlite.sqlcipher.android.AndroidDatabaseResults.getInt(AndroidDatabaseResults.java:168) 
W/System.err﹕ at com.j256.ormlite.field.types.IntegerObjectType.resultToSqlArg(IntegerObjectType.java:37) 
W/System.err﹕ at com.j256.ormlite.field.BaseFieldConverter.resultToJava(BaseFieldConverter.java:24) 
W/System.err﹕ at com.j256.ormlite.field.FieldType.resultToJava(FieldType.java:819) 
W/System.err﹕ at com.j256.ormlite.stmt.mapped.BaseMappedQuery.mapRow(BaseMappedQuery.java:60) 
W/System.err﹕ at com.j256.ormlite.stmt.SelectIterator.getCurrent(SelectIterator.java:270) 
W/System.err﹕ at com.j256.ormlite.stmt.SelectIterator.nextThrow(SelectIterator.java:161) 
W/System.err﹕ at com.j256.ormlite.stmt.StatementExecutor.query(StatementExecutor.java:202) 
W/System.err﹕ at com.j256.ormlite.stmt.StatementExecutor.queryForAll(StatementExecutor.java:118) 
W/System.err﹕ at com.j256.ormlite.dao.BaseDaoImpl.queryForAll(BaseDaoImpl.java:241) 
W/System.err﹕ at database.Database$ObjectsIterator.start(Database.java:221) 
W/System.err﹕ at fragments.F_BackupLocal$LocalBackup.doInBackground(F_BackupLocal.java:429) 
W/System.err﹕ at fragments.F_BackupLocal$LocalBackup.doInBackground(F_BackupLocal.java:368) 
W/System.err﹕ at android.os.AsyncTask$2.call(AsyncTask.java:288) 
W/System.err﹕ at java.util.concurrent.FutureTask.run(FutureTask.java:237) 
W/System.err﹕ at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231) 

Я буду обновлять этот пост до тех пор, как я узнаю, где проблема.

ответ

0

Я, наконец, исправил проблему.

В соответствии с этим documentation - В SQLite все, что вы можете сделать, - это переименование имени таблицы и добавление нового столбца. Вы не можете переименовать или удалить столбец или изменить ограничения.

Мое окончательное решение было добавить таблицу с новым полем, и оставить старую, как мертвый.

private void renameDB_Record_Item_Columns(ConnectionSource connectionSource) { 
    List<DB_RecordItem> recordItems; 
    List<JSONObject> objects = new ArrayList<>(); 
    try { 
     Dao<DB_RecordItem, String> dao = DaoManager.createDao(connectionSource, DB_RecordItem.class); 
     dao.executeRaw(String.format("ALTER TABLE %s ADD COLUMN %s INTEGER;", "db_recorditem", "file_id")); 

     recordItems = Database.getRecordItems().queryForAll(); 
     QueryBuilder<DB_RecordItem, String> qb = dao.queryBuilder(); 
     // Query for all items. 
     for (DB_RecordItem item : recordItems) { 
      qb.where().eq("id", item.getId()); 
      CloseableIterator<DB_RecordItem> iterator = dao.iterator(qb.prepare()); 

      GenericRawResults<String[]> rawResults = dao.queryRaw("select file from db_recorditem where id = " + item.getId() + ";"); 

      try { 
       int file_id = Integer.valueOf(rawResults.getResults().get(0)[0]); 
        if (file_id != -1) { 
         // If file_id it is not -1, then the recrod item had a file_id. 
         item.assignFile(new DB_File().setId(file_id)); 
         item.update(); 
        } 
      } finally { 
       iterator.closeQuietly(); 
      } 
     } 
    } catch (Exception e) { 
     Log.i("DatabaseLog", "Crash."); 
     e.printStackTrace(); 
    } 
} 

Во всяком случае, если кто-то найти правильный способ, как удалить и заново создать таблицу, пожалуйста, поделитесь. :)