EnergySpectrumAnalyer/src/GvfToCsv/sqliteread.cpp

300 lines
8.5 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "sqliteread.h"
#include <QtConcurrent>
SQLiteReadWrite::SQLiteReadWrite(QObject *parent)
: QObject(parent)
{
m_connectionName = QString("SQLiteConnection_%1").arg(reinterpret_cast<quintptr>(this));
idValue = 0;
m_stopRequested = false;
}
SQLiteReadWrite::~SQLiteReadWrite()
{
if (!m_isClosed) {
closeDatabase();
}
QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
}
bool SQLiteReadWrite::openDatabase(const QString &dbPath)
{
QMutexLocker locker(&m_mutex);
if (!m_isClosed) {
closeDatabase();
}
// 确定数据库路径
QString path = dbPath;
if (path.isEmpty()) {
QString appDir = QCoreApplication::applicationDirPath();
path = QDir(appDir).filePath("test_readwrite.db");
}
m_dbPath = path;
// 打开数据库
m_database = QSqlDatabase::addDatabase("QSQLITE", m_connectionName);
m_database.setDatabaseName(m_dbPath);
if (!m_database.open()) {
log(QString("打开数据库失败: %1").arg(m_database.lastError().text()));
return false;
}
// 启用外键和WAL模式提高并发性能
QSqlQuery query(m_database);
// 开启外键约束
if (!query.exec("PRAGMA foreign_keys = ON;")) {
log(QString("启用外键失败: %1").arg(query.lastError().text()));
}
// 开启WAL模式写时复制提高读写并发性能
if (!query.exec("PRAGMA journal_mode = WAL;")) {
log(QString("启用WAL模式失败: %1").arg(query.lastError().text()));
}
// // 设置同步模式(在安全性和性能之间权衡)
// if (!query.exec("PRAGMA synchronous = NORMAL;")) {
// log(QString("设置同步模式失败: %1").arg(query.lastError().text()));
// }
// 设置缓存大小
if (!query.exec("PRAGMA cache_size = 10000;")) {
log(QString("设置缓存大小失败: %1").arg(query.lastError().text()));
}
m_isClosed = false;
log(QString("数据库打开成功: %1").arg(m_dbPath));
return true;
}
void SQLiteReadWrite::closeDatabase()
{
QMutexLocker locker(&m_mutex);
if (m_isClosed) {
return;
}
m_isClosed = true;
if (m_database.isOpen()) {
m_database.close();
log("数据库已关闭");
}
if (QSqlDatabase::contains(m_connectionName)) {
QSqlDatabase::removeDatabase(m_connectionName);
}
QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
}
void SQLiteReadWrite::startReadWriteOperation()
{
if (!m_database.isOpen()) {
emit operationCompleted(false, "数据库未打开");
return;
}
m_stopRequested = false;
//在单独的线程中执行避免阻塞UI
QtConcurrent::run(this, &SQLiteReadWrite::processReadWrite);
}
void SQLiteReadWrite::stopOperation()
{
m_stopRequested = true;
log("stop requese send");
}
void SQLiteReadWrite::processReadWrite()
{
m_timer.start();
log("开始边读边写操作...");
try {
processWithMultipleConnections();
if (!m_stopRequested) {
qint64 elapsed = m_timer.elapsed();
QString message = QString("操作完成,总耗时: %1 毫秒").arg(elapsed);
log(message);
emit operationCompleted(true, message);
} else {
emit operationCompleted(false, "quxiao");
}
} catch (const std::exception &e) {
log(QString("发生异常: %1").arg(e.what()));
emit operationCompleted(false, QString("异常: %1").arg(e.what()));
}
}
void SQLiteReadWrite::processWithMultipleConnections()
{
const QString readConnName = m_connectionName + "_read";
int totalRecords = 0;
int processedRecords = 0;
bool readSuccess = false;
{
QSqlDatabase readDb = QSqlDatabase::addDatabase("QSQLITE", readConnName);
readDb.setDatabaseName(m_dbPath);
if (!readDb.open()) {
QString logMsg = QString("打开读取连接失败: %1").arg(readDb.lastError().text());
log(logMsg.toUtf8().constData());
emit operationCompleted(false, "无法打开数据库连接");
return;
}
{
QSqlQuery optimizeQuery(readDb);
optimizeQuery.exec("PRAGMA journal_mode = WAL;");
optimizeQuery.exec("PRAGMA synchronous = OFF;");
optimizeQuery.exec("PRAGMA cache_size = -200000;"); // 200MB缓存
optimizeQuery.exec("PRAGMA temp_store = MEMORY;");
optimizeQuery.exec("PRAGMA mmap_size = 2147483648;"); // 2GB内存映射
optimizeQuery.exec("PRAGMA query_only = ON;");
optimizeQuery.finish();
}
{
QSqlQuery countQuery(readDb);
if (countQuery.exec("SELECT COUNT(*) FROM lmdatainfov2")) {
countQuery.next();
totalRecords = countQuery.value(0).toInt();
}
countQuery.finish();
}
if (totalRecords == 0) {
log("数据库中无记录");
readDb.close();
emit operationCompleted(false, "数据库中无有效数据");
return;
}
QString totalMsg = QString("GVF数据库总记录数: %1 条").arg(totalRecords);
log(totalMsg.toUtf8().constData());
const int pageSize = 200;
int lastId = 0;
m_DataBaseList.clear();
m_DataBaseList.reserve(totalRecords);
while (!m_stopRequested) {
QSqlQuery readQuery(readDb);
readQuery.setForwardOnly(true);
readQuery.prepare("SELECT id, data FROM lmdatainfov2 WHERE id > :lastId ORDER BY id LIMIT :limit");
readQuery.bindValue(":lastId", lastId);
readQuery.bindValue(":limit", pageSize);
if (!readQuery.exec()) {
QString errMsg = QString("数据读取失败: %1").arg(readQuery.lastError().text());
log(errMsg.toUtf8().constData());
readQuery.finish();
break;
}
int pageRecords = 0;
while (readQuery.next() && !m_stopRequested) {
DataBaseStruct data;
data.id = readQuery.value(0).toInt();
data.data = readQuery.value(1).toByteArray();
m_DataBaseList.append(data);
lastId = data.id;
pageRecords++;
}
readQuery.finish();
readQuery.clear();
if (pageRecords == 0) {
break;
}
processedRecords += pageRecords;
int remainingRecords = totalRecords - processedRecords;
int progress = (processedRecords * 100) / totalRecords;
emit progressUpdated(progress, processedRecords, totalRecords);
}
QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
readDb.close();
readSuccess = true;
}
QThread::msleep(50);
if (QSqlDatabase::contains(readConnName)) {
QSqlDatabase::removeDatabase(readConnName);
}
QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
}
QSqlDatabase SQLiteReadWrite::createConnection()
{
QString connName = QString("TempConnection_%1_%2")
.arg(m_connectionName)
.arg(QDateTime::currentMSecsSinceEpoch());
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE", connName);
db.setDatabaseName(m_dbPath);
if (!db.open()) {
log(QString("创建临时连接失败: %1").arg(db.lastError().text()));
}
return db;
}
void SQLiteReadWrite::log(const QString &message)
{
QString timestamp = QDateTime::currentDateTime().toString("hh:mm:ss.zzz");
QString logMsg = QString("[%1] %2").arg(timestamp).arg(message);
emit logMessage(logMsg);
}
QVector<DataBaseStruct> SQLiteReadWrite::DataBaseList() const
{
QMutexLocker locker(&m_mutex);
return m_DataBaseList;
}
QString SQLiteReadWrite::getMeasureStartTime()
{
QMutexLocker locker(&m_mutex);
if (m_isClosed || !m_database.isOpen())
{
log("Database not open, cannot read statistic starttime");
return "";
}
QSqlQuery query(m_database);
// lmstatisticinfov2 存储本次测量标准起止时间
if (!query.exec("SELECT starttime FROM lmstatisticinfov2 LIMIT 1;"))
{
log(QString("Query lmstatisticinfov2 failed: %1").arg(query.lastError().text()));
return "";
}
if (query.next())
{
return query.value("starttime").toString();
}
log("lmstatisticinfov2 table has no starttime record");
return "";
}
void SQLiteReadWrite::setIdValue(int value)
{
idValue = value;
}