0

I wrote extension functions for reading from cursor:

fun SQLiteDatabase.query(table: String,
                         columns: Array<String>,
                         selection: String? = null,
                         selectionArgs: Array<String>? = null): Cursor =
        query(table, columns, selection, selectionArgs, null, null, null)

fun Cursor.readRows(onRowRead: (Cursor) -> Unit) {
    if(moveToFirst()) {
        do {
            onRowRead(this)
        } while (moveToNext())
    }
}

fun Cursor.getString(field: String): String = getString(getColumnIndex(field))
fun Cursor.getInt(field: String) = getInt(getColumnIndex(field))

And it mostly works perfect. But recently happened strange error in the followng SQLiteOpenHelper function:

fun loadPresentationStatistic(stringParser: (String) -> PresentationStatistic): ArrayList<PresentationStatisticInformation> {
    val db = readableDatabase
    val c = db.query(TABLE_PRESENTATION_STATISTIC, arrayOf(ROW_ID, ROW_PRESENTATION_STATISTIC))
    val result = arrayListOf<PresentationStatisticInformation>()
    c.readRows {
        result.add(PresentationStatisticInformation(it.getInt(ROW_ID),stringParser(it.getString(ROW_PRESENTATION_STATISTIC))))
    }
    c.close()
    return result
}

Error stacktrace:

java.lang.IllegalStateException: Couldn't read row 0, col 0 from CursorWindow. Make sure the Cursor is initialized correctly before accessing data from it. android.database.CursorWindow.nativeGetLong(Native Method) android.database.CursorWindow.getLong(CursorWindow.java:511) android.database.CursorWindow.getInt(CursorWindow.java:578) android.database.AbstractWindowedCursor.getInt(AbstractWindowedCursor.java:84) com.example.DBWorkerKt.getInt(DBWorker.kt:480) com.example.DBHelper$loadPresentationStatistic$1.invoke(DBWorker.kt:342)

If I get it right, that means moveToFirst returns true for empty cursor, so getInt function throws this exception. How could that be?

The worst thing is that I can't reproduce it. It happens only on one particular device - all other users works as they should.

Ircover
  • 2,406
  • 2
  • 22
  • 42
  • Usual reason for these is trying to read too large rows that don't fit a cursor window, and there's a cursor window alloc failure seen in logcat before the crash. – laalto Aug 01 '19 at 14:16
  • @laalto Does it mean that a single row is too large? Is there any chance to get data from it? – Ircover Aug 01 '19 at 14:50
  • Yep, the cursor window needs to fit at least one row. By default the limit is 2MB. There are some hacks to change it (https://stackoverflow.com/questions/11340257/sqlite-android-database-cursor-window-allocation-of-2048-kb-failed) but overall I believe you'd be better of by redesigning your schema in a way that does not result in huge rows. – laalto Aug 01 '19 at 14:59
  • @laalto Regardless I will change schema or not, I need solution to get already writen data from this user. So... I need hack, yep. – Ircover Aug 01 '19 at 17:46
  • check this answer. https://stackoverflow.com/questions/21432556/android-java-lang-illegalstateexception-couldnt-read-row-0-col-0-from-cursorw also make sure you dont have conflict in multithreading. – Hayk Melkonyan Aug 01 '19 at 21:10

0 Answers0