2011-03-19 5 views
3

Je suis en train de créer une application basée sur Qt pour surveiller et capturer des flux de données à partir d'un port série. Les données sont tracées en temps réel, envoyées via TCP et stockées dans une base de données SQLite. Malheureusement, j'ai trouvé que les insertions de SQLite font que l'interface graphique ne répond plus, car j'effectue la manipulation de données en série, le traçage, la transmission TCP et l'insertion de base de données dans le contexte de la boucle principale. J'ai recherché séparer les insertions de base de données sur un autre fil et ai trouvé le code suivant.Qt Requêtes de base de données SQL SQL Server

#include <QObject> 
#include <QDebug> 
#include <QStringList> 
#include <QSqlDatabase> 
#include <QSqlQuery> 
#include <QSqlError> 
#include <QVariant> 
#include <QObject> 
#include <QList> 
#include <QThread> 
#include <QMutex> 
#include <QWaitCondition> 
#include <QSqlDatabase> 
#include <QSqlRecord> 
#include <QString> 
#include "mMessage.h" 
// The class that does all the work with the database. This class will 
// be instantiated in the thread object's run() method. 
class Worker : public QObject 
{ 
    Q_OBJECT 
    public: 
    Worker(QObject* parent = 0); 
    ~Worker(); 
    bool insertADC(mMessage* insertMessage); 
    public slots: 
    void slotExecute(mMessage* insertMessage); 
    signals: 
    void queryResult(bool); 
    private: 
    QSqlDatabase m_database; 
    bool m_databaseOpen; 
    void prepareQueries(); 
    QSqlQuery *m_accelerometerQuery; 
    QSqlQuery *m_adcQuery; 
    QSqlQuery *m_metricsQuery; 
    QSqlQuery *m_rssiQuery; 
}; 

class mDatabaseThread : public QThread 
{ 
    Q_OBJECT 
    public: 
    mDatabaseThread(QObject *parent = 0); 
    ~mDatabaseThread(); 
    void executeInsertion(mMessage* insertMessage); 
    signals: 
    void progress(const QString& msg); 
void ready(bool); 
    protected: 
    void run(); 
    signals: 
    void executefwd(mMessage* insertMessage); 
    private: 
    Worker* m_worker; 
}; 

RPC DOSSIER

#include "mDatabaseThread.h" 
    // 

    Worker::Worker(QObject* parent) 
     : QObject(parent) 
    { 
     // thread-specific connection, see db.h 
     m_database = QSqlDatabase::addDatabase("QSQLITE", 
               "WorkerDatabase"); // named connection 
     m_database.setDatabaseName("trainingX.db3"); 
     if (!m_database.open()) 
     { 
      qWarning() << "Unable to connect to database, giving up:" << m_database.lastError().text(); 
      m_databaseOpen = false; 
      return; 
     } 
    m_databaseOpen = true; 

    } 

    Worker::~Worker() 
    { 
     //close the database 
     // m_database.close(); 
     // m_database.removeDatabase("trainingX.db3"); 
    } 
    void Worker::prepareQueries() 
    { 
     if (m_databaseOpen) 
     { 
     m_accelerometerQuery->prepare("INSERT INTO accelerometer (key, timestamp, nickname, unitid," 
            "sectorid, acc_x, acc_y, acc_z) " 
            "VALUES (NULL, :timestamp, :nickname, :unitid, :sectorid," 
            ":acc_x, :acc_y, :acc_z)"); 

     m_adcQuery->prepare("INSERT INTO adc (key, timestamp, nickname, unitid, sectorid," 
         "adc0, adc1, adc2, adc3, adc4, adc5, adc6, adc7) " 
         "VALUES (NULL, :timestamp, :nickname, :unitid, :sectorid," 
         ":adc0, :adc1, :adc2, :adc3, :adc4, :adc5, :adc6, :adc7)"); 

     m_metricsQuery->prepare("INSERT INTO metrics (key, timestamp, nickname, unitid, sectorid, " 
          "acc_temp, unit_temp, unit_pressure, bpm_instant, bpm_average, base_pressure, base_temp) " 
          "VALUES (NULL, :timestamp, :nickname, :unitid, :sectorid," 
          ":acc_temp, :unit_temp, :unit_pressure, :bpm_instant, :bpm_average, :base_pressure, :base_temp)"); 

     m_rssiQuery->prepare("INSERT INTO rssi (key, timestamp, nickname, unitid, sectorid, " 
          "rssi_1, rssi_2, rssi_3, rssi_4, rssi_avg) " 
          "VALUES (NULL, :timestamp, :nickname, :unitid, :sectorid," 
          ":rssi_1, :rssi_2, :rssi_3, :rssi_4, :rssi_avg)"); 
     } 
    } 

    void Worker::slotExecute(mMessage* insertMessage) 
    { 
     m_accelerometerQuery = new QSqlQuery("WorkerDatabase"); 
     m_adcQuery = new QSqlQuery("WorkerDatabase"); 
     m_metricsQuery = new QSqlQuery("WorkerDatabase"); 
     m_rssiQuery = new QSqlQuery("WorkerDatabase"); 

     prepareQueries(); 

     insertADC(insertMessage); 
     //insertRSSI(insertMessage); 
     //insertAccelerometer(insertMessage); 
     //insertMetrics(insertMessage); 
     emit queryResult(true); 
    } 
bool Worker::insertADC(mMessage *insertMessage) 
{ 
    if (m_databaseOpen) 
    { 
      // m_adcQuery->bindValue(":key",0); 
      m_adcQuery->bindValue(":timestamp",insertMessage->m_timestamp); 
      m_adcQuery->bindValue(":nickname",insertMessage->m_nickname); 
      m_adcQuery->bindValue(":unitid",insertMessage->m_unitId.toInt()); 
      m_adcQuery->bindValue(":sectorid",insertMessage->m_sectorId.toInt()); 
      m_adcQuery->bindValue(":adc0",insertMessage->m_adc0.toInt()); 
      m_adcQuery->bindValue(":adc1",insertMessage->m_adc1.toInt()); 
      m_adcQuery->bindValue(":adc2",insertMessage->m_adc2.toInt()); 
      m_adcQuery->bindValue(":adc3",insertMessage->m_adc3.toInt()); 
      m_adcQuery->bindValue(":adc4",insertMessage->m_adc4.toInt()); 
      m_adcQuery->bindValue(":adc5",insertMessage->m_adc5.toInt()); 
      m_adcQuery->bindValue(":adc6",insertMessage->m_adc6.toInt()); 
      m_adcQuery->bindValue(":adc7",insertMessage->m_adc7.toInt()); 
      if (m_adcQuery->exec()) 
      { 
       return true; 
      } 
      else 
      { 
       qDebug() << "SQL ADC failed."; 
       qDebug() << m_adcQuery->lastError(); 
       return false; 
      } 
    } 
    else 
    { 
    //database isn't open 
    return false; 
    } 
} 
////database thread 

mDatabaseThread::mDatabaseThread(QObject *parent) 
    : QThread(parent) 
{ 
} 
mDatabaseThread::~mDatabaseThread() 
{ 
    delete m_worker; 
} 

void mDatabaseThread::executeInsertion(mMessage* insertMessage) 
{ 
    emit executefwd(insertMessage); // forwards to the worker 
} 

void mDatabaseThread::run() 
{ 
    emit ready(false); 
    // Create worker object within the context of the new thread 
    m_worker = new Worker(); 
    connect(this, SIGNAL(executefwd(mMessage*)), 
      m_worker, SLOT(slotExecute(mMessage*))); 
    connect(m_worker, SIGNAL(queryResult(bool)), this, SIGNAL(ready(bool))); 
    emit ready(true); 

    exec(); // our event loop 
} 

La classe mDatabaseThread a un objet travailleur qui envoie le travail de base de données. Les signaux et les fentes fonctionnent tous et se déclenchent correctement. Cependant, le QSqlQuery réel ne se plaint pas que la base de données n'est pas ouverte - mais quand je tente de le déboguer, je vois que m_database est réellement défini sur le bon fichier/paramètres. Il est basé sur une solution ici http://www.linuxjournal.com/article/9602. La classe mMessage est un objet qObject qui est également transmis correctement à l'objet m_worker. De la classe principale, j'appelle m_databaseThread-> start() dans le constructeur puis j'appelle la fonction executeInsertion (mMessage *). J'ai essayé de changer la façon dont m_database est initialisée ainsi que QSqlQueries mais il semble que peu importe ce que je fais, il se plaint que QSqlQuery ne trouve pas la connexion à la base de données.

Répondre

3

Vous étiez proche.

Étant donné que vous avez donné un nom à la base de données dans addDatabase() ("WorkerDatabase"), la connexion résultante n'est pas la valeur par défaut de l'application et ne sera pas renvoyée par QSqlDatabase().

En raison de cela, vous devez passer l'objet de base de données à vos QSqlQuery constructeurs:

m_accelerometerQuery = new QSqlQuery(m_database); 

Le constructeur que vous utilisez ici:

m_accelerometerQuery = new QSqlQuery("WorkerDatabase"); 

est:

QSqlQuery (const QString & query = QString(), QSqlDatabase db = QSqlDatabase()) 

Lorsque vous passez dans "WorkerDatabase" à ce qu'il est stocké en tant que requête SQL, et la base de données par défaut (inexistante) retournée par QSqlDatabase() est stockée pour la base de données.

+0

Je vais essayer maintenant, merci pour le conseil. Je savais que c'était quelque chose de stupide! – mhilmi

+0

Parfait. Bon appel, vous êtes un homme de beauté! – mhilmi

Questions connexes