У меня есть класс, который должен многократно выполнять пакетные вставки. Экземпляр QSqlQuery является членом этого класса. Сначала я попробовал этот код:
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();
}
Это не сработало. В созданном файле SQLite было 65536 байт, но в таблице cache_storage была только 1 строка (flushBuffer() вызывалась много раз). Похоже, что первый вызов execBatch() был выполнен успешно, а последующие вызовы молча терпели неудачу (они продолжали возвращать true). Я понял, что работает следующий код:
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();
}
У меня есть пара вопросов:
Нужно ли создавать и уничтожать QSqlQuery для каждого вызова execBatch()?
Если да, то почему последующие вызовы execBatch() делают вид, что выполняются успешно?
Как насчет большого размера файла в первом случае? (Там всего 2 столика, другой пустой)
Я должен упомянуть, что это часть приложения, работающего на ОС BlackBerry 10. Чтобы каждый раз не создавать и не уничтожать QSqlQuery, я также пытался вызвать query.clear() в конце flushBuffer(), но это, похоже, также удалило подготовленный SQL из экземпляра QSqlQuery (следующий вызов execBatch() не удался) .
РЕДАКТИРОВАТЬ: я старался каждый раз избегать синтаксического анализа SQL, поэтому я попытался сохранить m_setWithGeoQuery без изменений и просто сделать его копию в flushBuffer():
QSqlQuery query(m_setWithGeoQuery);
query.addBindValue(m_buffer.at(0));
...
Удивительно, но это не работает. Он ведет себя так же, как и первый фрагмент.