2013-12-26 3 views
0

У меня есть следующий код: result - это курсор.IllegalStateException: Не удалось прочитать строку 0, col -1 из CursorWindow, несмотря на проверку пустого курсора?

if (result.getCount() == 1 && result.getColumnCount() > 0) { 
     result.moveToFirst(); 
     int columnIndex = result.getColumnIndex(TrackerContract.WorkLog.COLUMN_BLOCK_IN); 
     long time = currentTimeMilliMinutes(); 
     sumTotal = time - result.getLong(columnIndex); 
    } 

Так что, хотя я проверяю строки и столбцы, он выдает ошибку в заголовке. Я не знаю, что еще я должен был сделать, чтобы предотвратить эту ошибку. Курсор должен иметь только 1 строку, 1 столбец, значение long, я проверил инструкцию sql через adb, и это кажется правильным.

РЕДАКТИРОВАТЬ:

Вот запрос:

Cursor result = db.rawQuery("SELECT MAX("+TrackerContract.WorkLog.COLUMN_BLOCK_IN+ 
      ") FROM "+TrackerContract.WorkLog.TABLE_NAME+" WHERE "+TrackerContract.WorkLog.COLUMN_FDP_BEGIN+ 
      "=(SELECT MAX("+TrackerContract.WorkLog.COLUMN_FDP_BEGIN+") FROM "+TrackerContract.WorkLog.TABLE_NAME+");", 
      null); 

Когда я ввести один и тот же SQL через ADB, я получить правильное длинное значение в качестве единственного возвращаемого значения (1 строки, 1 Col). Вот фактический оператор SQL, потому что моя кодировка не прошла правильно. Я планирую рефакторинг этого, чтобы использовать параметризованный метод запроса, а не raw sql, но на данный момент я просто убеждаюсь, что он работает, и использование исходных инструкций для меня проще.

select max(blockTimeEnd) from WorkLog where dutyDayStart=(select max(dutyDayStart) from WorkLog); 

трассировки стека:

12-25 16:55:00.477: E/AndroidRuntime(32708): Caused by: java.lang.IllegalStateException: Couldn't read row 0, col -1 from CursorWindow. Make sure the Cursor is initialized correctly before accessing data from it. 
12-25 16:55:00.477: E/AndroidRuntime(32708): at android.database.CursorWindow.nativeGetLong(Native Method) 
12-25 16:55:00.477: E/AndroidRuntime(32708): at android.database.CursorWindow.getLong(CursorWindow.java:507) 
12-25 16:55:00.477: E/AndroidRuntime(32708): at android.database.AbstractWindowedCursor.getLong(AbstractWindowedCursor.java:75) 
12-25 16:55:00.477: E/AndroidRuntime(32708): at com.berrmal.timetracker.MainActivity.currentRest(MainActivity.java:503) 
12-25 16:55:00.477: E/AndroidRuntime(32708): at com.berrmal.timetracker.MainActivity.updateTimeTotals(MainActivity.java:567) 
12-25 16:55:00.477: E/AndroidRuntime(32708): at com.berrmal.timetracker.MainActivity.populateViews(MainActivity.java:187) 
12-25 16:55:00.477: E/AndroidRuntime(32708): at com.berrmal.timetracker.MainActivity.onResume(MainActivity.java:183) 

Edit 2: сделал некоторые протоколирования/отладки, имя столбца в курсоре возвращаемые max(blockTimeEnd), где он должен быть blockTimeEnd. Это явно ошибка.

+1

Опубликуйте журнал ошибок и запрос или полный метод, если это возможно. – jagmohan

+0

@ singh.jagmohan - сделано. –

ответ

0

Глядя на сообщение об ошибке, result.getColumnIndex(TrackerContract.WorkLog.COLUMN_BLOCK_IN) возвращает -1, так как он не может найти столбец. Из Android documentationgetColumnIndex на:

Returns the zero-based index for the given column name, or -1 if the column doesn't exist.

Убедитесь, что TrackerContract.WorkLog.COLUMN_BLOCK_IN является собственным именем столбца.

UPDATE:

Как вы используете SELECT MAX(blockTimeEnd), возвращенное имя столбца не blockTimeEnd. Изменение выбора части вашего запроса, чтобы использовать псевдоним SELECT MAX(blockTimeEnd) AS blockTimeEnd или в случае с использованием констант:

Cursor result = db.rawQuery("SELECT MAX("+TrackerContract.WorkLog.COLUMN_BLOCK_IN+ 
     ") AS " + TrackerContract.WorkLog.COLUMN_BLOCK_IN + " FROM "+TrackerContract.WorkLog.TABLE_NAME+" WHERE "+TrackerContract.WorkLog.COLUMN_FDP_BEGIN+ 
     "=(SELECT MAX("+TrackerContract.WorkLog.COLUMN_FDP_BEGIN+") FROM "+TrackerContract.WorkLog.TABLE_NAME+");", 
     null); 

В качестве альтернативы, прочитать колонку по номеру в вашем коде, как вы знаете, у вас есть только один вернулся:

if (result.getCount() == 1 && result.getColumnCount() > 0) { 
    result.moveToFirst(); 
    long time = currentTimeMilliMinutes(); 
    sumTotal = time - result.getLong(0); 
} 
+0

Спасибо. Я не понимаю, почему код пытается получить доступ к столбцуIndex -1, оператор if проверяет, имеет ли курсор ровно 1 строку и число столбцов> 0, поэтому, если количество столбцов равно -1, эта строка не должна выполняться, правильно? –

+0

Смотрите мое обновление. Проблема в том, что если вы используете агрегированную функцию, имя возвращаемого столбца отличается. См. Мое обновление для решений. – Szymon

0

Я нашел ошибку: при использовании оператора sql SELECT max(column) FROM table WHERE..." представляется, что имя возвращенного столбца: max(column), а не column.

Возможно, это общеизвестно, я начинающий SQL, но мне это было непонятно после прочтения документации функции max().

Я изменил линию

if (result.getCount() == 1 && 
      (columnIndex = result.getColumnIndex(TrackerContract.WorkLog.COLUMN_BLOCK_IN)) >= 0) { 

в

if (result.getCount() == 1 && 
      (columnIndex = result.getColumnIndex("max("+TrackerContract.WorkLog.COLUMN_BLOCK_IN + ")")) >= 0) { 

и функция теперь работает как задумано.

Поскольку я знаю, по дизайну, мой запрос должен возвращать только столбец 1 строки 1, я мог бы также просто выбрать индекс столбца 0 без проверки имени.

Смежные вопросы