0

I have a code which performs 3 async make operation on a database. This code crashs if I run 3 async operations, but if it's only one there is no problem. How to organize multi threaded operation on SQLite? I have tried QMutex.lock but It did not work.

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QtConcurrent/QtConcurrentRun>
#include <database.h>


int main(int argc, char *argv[])
{

QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
Database *db0=new Database();
Database *db1=new Database();
Database *db2=new Database();

QString param0="Select LastUpdateDate From TableLastUpdateLog Where TableName='T1'";
 QString param1="Select LastUpdateDate From TableLastUpdateLog Where TableName='T2'";
  QString param2="Select LastUpdateDate From TableLastUpdateLog Where TableName='T3'";


QtConcurrent::run(db0,&Database::Select,param0);
QtConcurrent::run(db1,&Database::Select,param1);
QtConcurrent::run(db2,&Database::Select,param2);



return app.exec();

}

database.cpp

void Database::Select(QString query) {

m_db=QSqlDatabase::addDatabase("QSQLITE","myconn");
m_db.setDatabaseName("./mytask.db");
bool result=m_db.open();
if(result==false)
    qDebug()<<"Failed";
else
{
    qDebug()<<"Connection is Success";
    m_qry=new QSqlQuery(m_db);
    m_qry->exec("PRAGMA foreign_keys = ON;");
    m_qry->exec("DSQLITE_THREADSAFE=2");
    m_qry->prepare(query);
    if(m_qry->exec()!=true)
    {
        qDebug()<<"Query Failed:"<<m_qry->lastError();
        qDebug()<<m_qry->lastQuery();
    }
    else
    {
        QSqlRecord rec=m_qry->record();
        while(m_qry->next())
        {
            qDebug()<<m_qry->value("LastUpdateDate").toDateTime();
        }

    }
}

m_db.close();
m_db.removeDatabase("myconn");

//mutex.unlock();   
}
UmNyobe
  • 22,539
  • 9
  • 61
  • 90
Kevin yudo
  • 233
  • 4
  • 15

1 Answers1

0

Your code crashes because you are still using the same connection to access the database from each thread. In Qt connections are identified by their names, ie the value "myconn" passed to addDatabase.

Not only Qt will misbehave, but sqlite driver too. From Qt docs

Warning: If you add a connection with the same name as an existing connection, 
the new connection replaces the old one. 

Your statement SQLITE_THREADSAFE=2 allow multithreading as long as no two threads attempt to use the same database connection, which is not the case.

The solution is to provide a different connection name for each of your objects.

UmNyobe
  • 22,539
  • 9
  • 61
  • 90