Android Sqlite - исключение: Индекс -1 запрошен, с размером 32 --- из-за большого размера? - PullRequest
0 голосов
/ 25 января 2020

В моем приложении я использую стандартный способ доступа к файлам базы данных Sqlite. Все отлично работает месяцами, но для одной указанной строки c в базе данных есть проблема. Данные в столбце имеют длину 7,265,161 байта.

При чтении этой строки я получаю следующую ошибку:

Запрошен индекс -1, размером 32

Стандартный код I использовать это:

List<CText> cTexts = new ArrayList<>();
try {
    Cursor cursor;
    String[] tableColumns = new String[]{"book", "chapter", "fromvorm", "tovorm", "data"};
    String[] whereArgs = new String[]{"" + bookNumber, "" + chapterNumber};
    cursor = db.query(TABLE_CTEXT, tableColumns, "book = ? and chapter = ?", whereArgs, null, null, "fromvorm");
    cursor.moveToFirst();
    while (!cursor.isAfterLast()) {
        cTexts.add(new CText(cursor.getInt(0),
                cursor.getInt(1), cursor.getInt(2),
                cursor.getInt(3), cursor.getString(4)));
        cursor.moveToNext();
    }
    cursor.close();
} catch (Exception e) {
    Logger.e("Get ctext exception: " + e.getMessage(), e);
    return null;
}

Можете ли вы помочь решить?

ОБНОВЛЕНИЕ : благодаря @ekimro у нас есть решение!

После дальнейшего изучения я вижу, что разбиение файла 7 МБ на части по 1 МБ приводит к ответу. Требуется около 30 секунд, чтобы получить этот ответ.

1 Ответ

1 голос
/ 26 января 2020

Объясняемая вами проблема превышает 4Mb для CursorWindow.

Решение - это перепроектирование схемы (сохранение данных в виде блоков размером от маленького до 4Mb (например, 256 КБ)) или получение данных в виде фрагмента, маленького размера, например 256 КБ.

Последнее, как SQL

WITH RECURSIVE control(startchar,endchar,limiter,book,chapter,seq) AS (
    SELECT 1,256 * 1024, (SELECT max(length(data)) FROM ctext WHERE book = 'B2' AND chapter = '1'),'B2','1',0
    UNION ALL SELECT endchar + 1,endchar + (256 * 1024), limiter,book,chapter,seq +1 FROM control WHERE endchar < limiter LIMIT 100
)
SELECT 
    seq AS sequence,
    book AS book,
    chapter AS chapter,
    (SELECT fromvorm FROM CTEXT WHERE ctext.book = control.book AND ctext.chapter = control.chapter) AS fromvorm,
    (SELECT tovorm FROM CTEXT WHERE ctext.book = control.book AND ctext.chapter = control.chapter) AS tovorm,
    (SELECT substr(ctext.data,control.startchar,control.endchar) FROM CTEXT  WHERE ctext.book = control.book AND ctext.chapter = control.chapter ) AS chunk
FROM control  ORDER BY sequence;

Получение с данными теста (закрыть 7Mb)

enter image description here

Android как (это только 1 книга / глава, требующая l oop книгу и нуждающаяся в l oop главе, если больше). Не проверено, поэтому нужно проверить.

    List<CText> cTexts = new ArrayList<>();
    Cursor cursor;
    StringBuilder data = new StringBuilder();
    String[] whereArgs = new String[]{"" + bookNumber, "" + chapterNumber, "" + bookNumber, "" + chapterNumber};
    cursor = db.rawQuery(
            "WITH RECURSIVE control(startchar,endchar,limiter,book,chapter,seq) AS " +
                    "(" +
                    "SELECT 1,256 * 1024, " +

                    "(SELECT max(length(data)) " +
                    "FROM ctext " +
                    "WHERE book = ? " +
                    "AND chapter = ?)," +

                    "?," +
                    "?," +
                    "0 " +
                    "UNION ALL SELECT " +
                    "endchar + 1," +
                    "endchar + (256 * 1024), " +
                    "limiter," +
                    "book," +
                    "chapter," +
                    "seq +1 " +
                    "FROM control " +
                    "WHERE endchar < limiter LIMIT 100" +
                    ") SELECT " +
                    "   seq AS sequence," +
                    "   book AS book," +
                    "   chapter AS chapter," +
                    "   (SELECT fromvorm " +
                    "       FROM CTEXT" +
                    "        WHERE ctext.book = control.book " +
                    "       AND ctext.chapter = control.chapter" +
                    "   ) AS fromvorm," +

                    "   (SELECT tovorm " +
                    "       FROM CTEXT " +
                    "       WHERE ctext.book = control.book " +
                    "       AND ctext.chapter = control.chapter" +
                    "   ) AS tovorm,    " +

                    "   (SELECT substr(ctext.data,control.startchar,control.endchar) " +
                    "       FROM CTEXT " +
                    "       WHERE ctext.book = control.book " +
                    "       AND ctext.chapter = control.chapter " +
                    "   ) AS chunk " +

                    "FROM control;"
            , whereArgs
    );
    while (cursor.moveToNext()) {
        data.append(cursor.getString(cursor.getColumnIndex("chunk")));
    }
    if (cursor.moveToFirst()) {
        cTexts.add(new CText(cursor.getInt(0),
                cursor.getInt(1), cursor.getInt(2),
                cursor.getInt(3), data.toString()));
    }
...