void RowLoader::process (Task & t) { QString sLimitQuery; if(query.startsWith("PRAGMA", Qt::CaseInsensitive) || query.startsWith("EXPLAIN", Qt::CaseInsensitive)) { sLimitQuery = query; } else { // Remove trailing trailing semicolon QString queryTemp = rtrimChar(query, ';'); // If the query ends with a LIMIT statement take it as it is, if not append our own LIMIT part for lazy population if(queryTemp.contains(QRegExp("LIMIT\\s+.+\\s*((,|\\b(OFFSET)\\b)\\s*.+\\s*)?$", Qt::CaseInsensitive))) sLimitQuery = queryTemp; else sLimitQuery = queryTemp + QString(" LIMIT %1, %2;").arg(t.row_begin).arg(t.row_end-t.row_begin); } statement_logger(sLimitQuery); QByteArray utf8Query = sLimitQuery.toUtf8(); sqlite3_stmt *stmt; int status = sqlite3_prepare_v2(pDb.get(), utf8Query, utf8Query.size(), &stmt, nullptr); auto row = t.row_begin; if(SQLITE_OK == status) { const int num_columns = headers.size(); while(!t.cancel && sqlite3_step(stmt) == SQLITE_ROW) { Cache::value_type rowdata; for(int i=0;i<num_columns;++i) { if(sqlite3_column_type(stmt, i) == SQLITE_NULL) { rowdata.append(QByteArray()); } else { int bytes = sqlite3_column_bytes(stmt, i); if(bytes) rowdata.append(QByteArray(static_cast<const char*>(sqlite3_column_blob(stmt, i)), bytes)); else rowdata.append(QByteArray("")); } } QMutexLocker lk(&cache_mutex); cache_data.set(row++, std::move(rowdata)); } } sqlite3_finalize(stmt); if(row != t.row_begin) emit fetched(t.token, t.row_begin, row); }
int SqliteTableModel::getQueryRowCount() { // Return -1 if there is an error int retval = -1; // Use a different approach of determining the row count when a EXPLAIN or a PRAGMA statement is used because a COUNT fails on these queries if(m_sQuery.startsWith("EXPLAIN", Qt::CaseInsensitive) || m_sQuery.startsWith("PRAGMA", Qt::CaseInsensitive)) { // So just execute the statement as it is and fetch all results counting the rows sqlite3_stmt* stmt; QByteArray utf8Query = m_sQuery.toUtf8(); if(sqlite3_prepare_v2(m_db->_db, utf8Query, utf8Query.size(), &stmt, NULL) == SQLITE_OK) { retval = 0; while(sqlite3_step(stmt) == SQLITE_ROW) retval++; sqlite3_finalize(stmt); // Return the results but also set the chunk size the number of rows to prevent the lazy population mechanism to kick in as using LIMIT // fails on this kind of queries as well m_chunkSize = retval; return retval; } } else { // If it is a normal query - hopefully starting with SELECT - just do a COUNT on it and return the results QString sCountQuery = QString("SELECT COUNT(*) FROM (%1);").arg(rtrimChar(m_sQuery, ';')); m_db->logSQL(sCountQuery, kLogMsg_App); QByteArray utf8Query = sCountQuery.toUtf8(); sqlite3_stmt* stmt; int status = sqlite3_prepare_v2(m_db->_db, utf8Query, utf8Query.size(), &stmt, NULL); if(status == SQLITE_OK) { status = sqlite3_step(stmt); if(status == SQLITE_ROW) { QString sCount = QString::fromUtf8((const char*)sqlite3_column_text(stmt, 0)); retval = sCount.toInt(); } sqlite3_finalize(stmt); } else { qWarning() << "Count query failed: " << sCountQuery; } } return retval; }
int RowLoader::countRows() { int retval = -1; // Use a different approach of determining the row count when a EXPLAIN or a PRAGMA statement is used because a COUNT fails on these queries if(query.startsWith("EXPLAIN", Qt::CaseInsensitive) || query.startsWith("PRAGMA", Qt::CaseInsensitive)) { // So just execute the statement as it is and fetch all results counting the rows sqlite3_stmt* stmt; QByteArray utf8Query = query.toUtf8(); if(sqlite3_prepare_v2(pDb.get(), utf8Query, utf8Query.size(), &stmt, nullptr) == SQLITE_OK) { retval = 0; while(sqlite3_step(stmt) == SQLITE_ROW) retval++; sqlite3_finalize(stmt); return retval; } } else { // If it is a normal query - hopefully starting with SELECT - just do a COUNT on it and return the results QString sCountQuery = QString("SELECT COUNT(*) FROM (%1);").arg(rtrimChar(query, ';')); statement_logger(sCountQuery); QByteArray utf8Query = sCountQuery.toUtf8(); sqlite3_stmt* stmt; int status = sqlite3_prepare_v2(pDb.get(), utf8Query, utf8Query.size(), &stmt, nullptr); if(status == SQLITE_OK) { status = sqlite3_step(stmt); if(status == SQLITE_ROW) { QString sCount = QString::fromUtf8(reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0))); retval = sCount.toInt(); } sqlite3_finalize(stmt); } else { qWarning() << "Count query failed: " << sCountQuery; } } return retval; }
void SqliteTableModel::fetchData(unsigned int from, unsigned to) { int currentsize = m_data.size(); QString sLimitQuery; if(m_sQuery.startsWith("PRAGMA", Qt::CaseInsensitive) || m_sQuery.startsWith("EXPLAIN", Qt::CaseInsensitive)) { sLimitQuery = m_sQuery; } else { // Remove trailing trailing semicolon QString queryTemp = rtrimChar(m_sQuery, ';'); // If the query ends with a LIMIT statement take it as it is, if not append our own LIMIT part for lazy population if(queryTemp.contains(QRegExp("LIMIT\\s+\\d+\\s*(,\\s*\\d+\\s*)?$", Qt::CaseInsensitive))) sLimitQuery = queryTemp; else sLimitQuery = QString("%1 LIMIT %2, %3;").arg(queryTemp).arg(from).arg(to-from); } m_db->logSQL(sLimitQuery, kLogMsg_App); QByteArray utf8Query = sLimitQuery.toUtf8(); sqlite3_stmt *stmt; int status = sqlite3_prepare_v2(m_db->_db, utf8Query, utf8Query.size(), &stmt, NULL); if(SQLITE_OK == status) { while(sqlite3_step(stmt) == SQLITE_ROW) { QByteArrayList rowdata; for (int i = 0; i < m_headers.size(); ++i) rowdata.append(QByteArray(static_cast<const char*>(sqlite3_column_blob(stmt, i)), sqlite3_column_bytes(stmt, i))); m_data.push_back(rowdata); } } sqlite3_finalize(stmt); beginInsertRows(QModelIndex(), currentsize, m_data.size()-1); endInsertRows(); }