Error "requested database does not belong to the calling thread"
-
wrote on 18 Apr 2023, 18:57 last edited by
I am using a QSqlDatabase connection (Postgres) in my main thread. I need to test whether the connection is alive continously for some other application logic. In case the connection is not available, the GUI would block until the test returns.
Therefore I have created a small connection testing class, inheriting from QThread. In run() I test the connection, using a function IsAlive(), which is also used by the main thread (having its own DB connection).
When the additional thread has cloned the DB and uses it for testing, the following error is logged: "QSqlDatabasePrivate::database: requested database does not belong to the calling thread." This is not just a warning, the db.open() actually fails because of that error.I have tried to use the cloneDatabase overload, using the database retrieved via name as parameter. Also, I stored the main threads database in the DbConnectionTest constructor, then cloning in run(), since calling QSqlDatabase::database(mainThreadConnectionName) in run() also emitted the same error. Doing that, I got rid of this single error message, but not the others, using db.open() in IsAlive().
void DbConnectionTest::run() { auto db = QSqlDatabase::cloneDatabase(cloneFromConnectionName, thisThreadsConnectionName); if (!db.isValid() qDebug() << "Cloning failed"; // this is never hit, also the db.connectionName() is correct QTimer timer; QObject::connect(&timer, &QTimer::timeout, this, &DbConnectionTest::test, Qt::DirectConnection); m_timer.start(m_updateRate); exec(); } // this is kind of a pseudo code, showing approx. what is done void DbConnectionTest::test() { emit isAlive(IsAlive(thisThreadsConnectionName)); // some main thread function connects to this signal } bool IsAlive(const QString& connectionName) { QSqlDatabase db = QSqlDatabase::database(connectionName, false); // the next line is always correct: the thread id and the connection name belong together as expected qDebug() << "DbConnectionTest::test " << db.connectionName() << " " << QThread::currentThreadId(); if (!db.isOpen()) db.open(); // this trigges the error, but when debugging, the thread id and connection name are fine if (db.isOpen()) { QSqlQuery query; static auto statement = QString("SELECT 1"); return query.prepare(statement) && query.exec() && query.next(); } return false; }
Has someone experienced similar issues or any hints how to solve this? Thanks in advance.
-
I am using a QSqlDatabase connection (Postgres) in my main thread. I need to test whether the connection is alive continously for some other application logic. In case the connection is not available, the GUI would block until the test returns.
Therefore I have created a small connection testing class, inheriting from QThread. In run() I test the connection, using a function IsAlive(), which is also used by the main thread (having its own DB connection).
When the additional thread has cloned the DB and uses it for testing, the following error is logged: "QSqlDatabasePrivate::database: requested database does not belong to the calling thread." This is not just a warning, the db.open() actually fails because of that error.I have tried to use the cloneDatabase overload, using the database retrieved via name as parameter. Also, I stored the main threads database in the DbConnectionTest constructor, then cloning in run(), since calling QSqlDatabase::database(mainThreadConnectionName) in run() also emitted the same error. Doing that, I got rid of this single error message, but not the others, using db.open() in IsAlive().
void DbConnectionTest::run() { auto db = QSqlDatabase::cloneDatabase(cloneFromConnectionName, thisThreadsConnectionName); if (!db.isValid() qDebug() << "Cloning failed"; // this is never hit, also the db.connectionName() is correct QTimer timer; QObject::connect(&timer, &QTimer::timeout, this, &DbConnectionTest::test, Qt::DirectConnection); m_timer.start(m_updateRate); exec(); } // this is kind of a pseudo code, showing approx. what is done void DbConnectionTest::test() { emit isAlive(IsAlive(thisThreadsConnectionName)); // some main thread function connects to this signal } bool IsAlive(const QString& connectionName) { QSqlDatabase db = QSqlDatabase::database(connectionName, false); // the next line is always correct: the thread id and the connection name belong together as expected qDebug() << "DbConnectionTest::test " << db.connectionName() << " " << QThread::currentThreadId(); if (!db.isOpen()) db.open(); // this trigges the error, but when debugging, the thread id and connection name are fine if (db.isOpen()) { QSqlQuery query; static auto statement = QString("SELECT 1"); return query.prepare(statement) && query.exec() && query.next(); } return false; }
Has someone experienced similar issues or any hints how to solve this? Thanks in advance.
Hi,
That looks a bit strange...
How are you starting your thread ?
Why are you forcing the direction connection for your timer ?
What happens if, rather than cloning, you create a new QSqlDatabse object ? -
I am using a QSqlDatabase connection (Postgres) in my main thread. I need to test whether the connection is alive continously for some other application logic. In case the connection is not available, the GUI would block until the test returns.
Therefore I have created a small connection testing class, inheriting from QThread. In run() I test the connection, using a function IsAlive(), which is also used by the main thread (having its own DB connection).
When the additional thread has cloned the DB and uses it for testing, the following error is logged: "QSqlDatabasePrivate::database: requested database does not belong to the calling thread." This is not just a warning, the db.open() actually fails because of that error.I have tried to use the cloneDatabase overload, using the database retrieved via name as parameter. Also, I stored the main threads database in the DbConnectionTest constructor, then cloning in run(), since calling QSqlDatabase::database(mainThreadConnectionName) in run() also emitted the same error. Doing that, I got rid of this single error message, but not the others, using db.open() in IsAlive().
void DbConnectionTest::run() { auto db = QSqlDatabase::cloneDatabase(cloneFromConnectionName, thisThreadsConnectionName); if (!db.isValid() qDebug() << "Cloning failed"; // this is never hit, also the db.connectionName() is correct QTimer timer; QObject::connect(&timer, &QTimer::timeout, this, &DbConnectionTest::test, Qt::DirectConnection); m_timer.start(m_updateRate); exec(); } // this is kind of a pseudo code, showing approx. what is done void DbConnectionTest::test() { emit isAlive(IsAlive(thisThreadsConnectionName)); // some main thread function connects to this signal } bool IsAlive(const QString& connectionName) { QSqlDatabase db = QSqlDatabase::database(connectionName, false); // the next line is always correct: the thread id and the connection name belong together as expected qDebug() << "DbConnectionTest::test " << db.connectionName() << " " << QThread::currentThreadId(); if (!db.isOpen()) db.open(); // this trigges the error, but when debugging, the thread id and connection name are fine if (db.isOpen()) { QSqlQuery query; static auto statement = QString("SELECT 1"); return query.prepare(statement) && query.exec() && query.next(); } return false; }
Has someone experienced similar issues or any hints how to solve this? Thanks in advance.
@enel said in Error "requested database does not belong to the calling thread":
QObject::connect(&timer, &QTimer::timeout, this, &DbConnectionTest::test, Qt::DirectConnection);
This is just wrong. Don't do that.
Use the worker approach to make sure everything is running the the thread you want.
-
Hi,
That looks a bit strange...
How are you starting your thread ?
Why are you forcing the direction connection for your timer ?
What happens if, rather than cloning, you create a new QSqlDatabse object ?@SGaist said in Error "requested database does not belong to the calling thread":
Why are you forcing the direction connection for your timer ?
To force the execution in the newly created thread I would guess - but it's just a really crappy design.
What happens if, rather than cloning, you create a new QSqlDatabse object ?
Will not make any difference :)
-
@SGaist said in Error "requested database does not belong to the calling thread":
Why are you forcing the direction connection for your timer ?
To force the execution in the newly created thread I would guess - but it's just a really crappy design.
What happens if, rather than cloning, you create a new QSqlDatabse object ?
Will not make any difference :)
@Christian-Ehrlicher said in Error "requested database does not belong to the calling thread":
@SGaist said in Error "requested database does not belong to the calling thread":
Why are you forcing the direction connection for your timer ?
To force the execution in the newly created thread I would guess - but it's just a really crappy design.
That's what I was thinking as well, I just wanted to know the motivation behind its use.
What happens if, rather than cloning, you create a new QSqlDatabse object ?
Will not make any difference :)
That's for completeness sake, I would find it strange that cloning fails when its goal is to avoid duplicating the code configuring a new connection.
-
wrote on 19 Apr 2023, 10:42 last edited by
Thanks for your comments.
I had tried the worker approach with no success. Now, that I have solved my issue, I have learned what was wrong with the worker approach: I had the parent set for my worker instance
new Worker(this)
, which prevents moving to the other thread.Also, I had to create the QSqlQuery for the database of the desired thread:
QSqlQuery query(QString("SELECT 1"), db)
. -
1/6