Home:ALL Converter>SQLite and QSqlQuery - multiple calls of execBatch() fail

SQLite and QSqlQuery - multiple calls of execBatch() fail

Ask Time:2014-03-04T20:29:31         Author:Andrej Repiský

Json Formatter

I have a class which needs to execute batch inserts repeatedly. QSqlQuery instance is a member of that class. At first I tried this code:

TOMCache::TOMCache(QObject *parent): QObject(parent) {    
    m_setWithGeoQuery.prepare("INSERT OR REPLACE INTO cache_storage(key, value, lat, lng, expiration) VALUES(?, ?, ?, ?, ?)");
}

void TOMCache::flushBuffer() {
    QSqlQuery &query = m_setWithGeoQuery;
    query.addBindValue(m_buffer.at(0));
    query.addBindValue(m_buffer.at(1));
    query.addBindValue(m_buffer.at(2));
    query.addBindValue(m_buffer.at(3));
    query.addBindValue(m_buffer.at(4));
    if(!query.execBatch())
        qWarning() << "-- execBatch() failed: " << query.lastError().text();
    m_buffer.clear();
    m_buffer << QVariantList() << QVariantList() << QVariantList() << QVariantList() << QVariantList();
}

That didn't work. The created SQLite file had 65536 Bytes, but there was only 1 row in the table cache_storage (flushBuffer() was called many times). It looks like the first call of execBatch() executed successfully and next calls silently failed (they kept returning true). I realized that the following code works:

void TOMCache::flushBuffer() {

    QSqlQuery query;
    query.prepare("INSERT OR REPLACE INTO cache_storage(key, value, lat, lng, expiration) VALUES(?, ?, ?, ?, ?)");
    query.addBindValue(m_buffer.at(0));
    query.addBindValue(m_buffer.at(1));
    query.addBindValue(m_buffer.at(2));
    query.addBindValue(m_buffer.at(3));
    query.addBindValue(m_buffer.at(4));
    if(!query.execBatch())
        qWarning() << "-- execBatch() failed: " << query.lastError().text();
    m_buffer.clear();
    m_buffer << QVariantList() << QVariantList() << QVariantList() << QVariantList() << QVariantList();
}

I have a couple of questions:

  1. Does QSqlQuery need to be created and destroyed for each call of execBatch()?

  2. If so, why do the subsequent calls of execBatch() pretend to execute successfully?

  3. What about the big file size in the first case? (There are only 2 tables, the other one is empty)

I should mention that this is part of an application running on BlackBerry 10 OS. In order to avoid creating and destroying QSqlQuery each time, I also tried to call query.clear() at the end of flushBuffer() but that seems to have removed also the prepared SQL from QSqlQuery instance (next call of execBatch() failed).

EDIT: I tried to avoid parsing the SQL each time, so I tried to keep m_setWithGeoQuery unmodified and just make a copy of it in flushBuffer():

    QSqlQuery query(m_setWithGeoQuery);
    query.addBindValue(m_buffer.at(0));
    ...

Surprisingly, it doesn't work. It behaves the same as the first snippet.

Author:Andrej Repiský,eproduced under the CC 4.0 BY-SA copyright license with a link to the original source and this disclaimer.
Link to original article:https://stackoverflow.com/questions/22171992/sqlite-and-qsqlquery-multiple-calls-of-execbatch-fail
yy