「ローカル」と「リモート」の 2 つの QSqlDatabase データベース接続があります。両方の接続を使用する関数があります (ローカル データベースからデータを取得し、リモート データベースに送信します)。QThread クラスからこの関数を実行すると、ローカル接続は機能しますが (予想されるデータを取得しました)、リモート接続は失敗します。しかし、この関数を QThread クラスの外 (main() 内) で実行すると、両方の接続が機能します。
接続を開こうとすると、「QSqlDatabasePrivate::database: データベースを開けません: QMYSQL: 接続できません」というエラー メッセージが表示されて、リモート接続が失敗します。その前に、接続が有効かどうか (isValid()) をテストしてみましたが、問題ありませんでした。また、接続が既に開いているかどうかも確認しましたが、そうではありませんでした。
この情報も見つけましたが、「ローカル」接続はスレッドから機能するため、これは問題ではない可能性があります。
スレッドと SQL モジュール 接続は、それを作成したスレッド内からのみ使用できます。スレッド間の接続の移動や、別のスレッドからのクエリの作成はサポートされていません。 http://doc.qt.io/qt-5/threads-modules.html#threads-and-the-sql-module
このエラーは、Qt 5.5.1、32 ビット、Ubuntu 14.04 で見つかりました。Raspberry Pi、Qt 5.6 でもテストされましたが、結果として「セグメンテーション違反」が発生しました。
なにが問題ですか?
main.c
main()
{
DataHandler dh();
DataHandlerThread dht(&dh); //pointer to dh to get access to dh functions from the thread
//here I run dh.foo() or dht.run(), never both functions
dh.foo();
dht.run();
...
}
datahandler.cpp
DataHandler::DataHandler()
{
m_dbLocal = QSqlDatabase::addDatabase("QMYSQL", "local");
m_dbLocal.setHostName("localhost");
...
m_dbRemote = QSqlDatabase::addDatabase("QMYSQL", "remote");
m_dbRemote.setHostName(...);
...
}
DataHandler::foo()
{
qDebug() << QSqlDatabase::connectionNames(); //always ("remote", "local")
m_dbLocal.isValid(); //always true
m_dbLocal.open(); //always true
m_dbRemote.isValid(); //always true
//true if foo() is called from main using dm.foo()
//QSqlDatabasePrivate::database: unable to open database: " QMYSQL: Unable to connect" if called from main using dmt.run()
m_dbRemote.open();
}
datahandlerthread.h
class DataHandlerThread : public QThread
{
Q_OBJECT
public:
explicit DataHandlerThread(DataHandler* dh);
private:
void run() Q_DECL_OVERRIDE;
DataHandler* m_dh;
};
datahandlerthread.cpp
DataHandlerThread::DataHandlerThread(DataHandler* dh)
{
m_dh = dh;
}
void DataHandlerThread::run()
{
m_dh->foo();
}