]> Some of my projects - localmylist.git/commitdiff
Add SqlAsyncQuery class.
authorAPTX <marek321@gmail.com>
Tue, 19 Mar 2013 22:22:09 +0000 (23:22 +0100)
committerAPTX <marek321@gmail.com>
Tue, 19 Mar 2013 22:22:09 +0000 (23:22 +0100)
localmylist/asyncquerytask.cpp [new file with mode: 0644]
localmylist/asyncquerytask.h [new file with mode: 0644]
localmylist/include/LocalMyList/SqlAsyncQuery [new file with mode: 0644]
localmylist/localmylist.pro
localmylist/sqlasyncquery.cpp [new file with mode: 0644]
localmylist/sqlasyncquery.h [new file with mode: 0644]
localmylist/sqlasyncqueryinternal.cpp [new file with mode: 0644]
localmylist/sqlasyncqueryinternal.h [new file with mode: 0644]

diff --git a/localmylist/asyncquerytask.cpp b/localmylist/asyncquerytask.cpp
new file mode 100644 (file)
index 0000000..78f3a25
--- /dev/null
@@ -0,0 +1,75 @@
+#include "asyncquerytask.h"
+
+#include <QSqlQuery>
+#include <QSqlError>
+#include <QSqlRecord>
+#include <QVector>
+#include "database.h"
+
+namespace LocalMyList {
+
+AsyncQueryTask::AsyncQueryTask(QObject *parent) :
+       AbstractTask(parent), m_query(0), m_result(0)
+{
+}
+
+AsyncQueryTask::~AsyncQueryTask()
+{
+}
+
+void AsyncQueryTask::setQuery(AsyncQuery *query)
+{
+       m_query = query;
+}
+
+Result *AsyncQueryTask::result() const
+{
+       return m_result;
+}
+
+
+QString AsyncQueryTask::taskSubject() const
+{
+       if (!m_query)
+               return QString();
+       return m_query->query;
+}
+
+bool AsyncQueryTask::canUseThreads() const
+{
+       return true;
+}
+
+void AsyncQueryTask::start()
+{
+       QSqlQuery q(db->connection());
+
+       q.prepare(m_query->query);
+
+       foreach(const BoundValue &v, m_query->boundValues)
+       {
+               q.bindValue(v.name, v.value, v.paramType);
+       }
+
+       m_result = new Internal::Result;
+       if (!q.exec())
+       {
+               m_result->error = q.lastError().text();
+       }
+       else
+       {
+               while (q.next())
+               {
+                       Internal::Row row(q.record().count());
+                       for (int i = 0; i < row.count(); ++i)
+                       {
+                               row[i].name = q.record().fieldName(i);
+                               row[i].value = q.value(i);
+                       }
+                       m_result->rows << row;
+               }
+       }
+       emit finished();
+}
+
+} // namespace LocalMyList
diff --git a/localmylist/asyncquerytask.h b/localmylist/asyncquerytask.h
new file mode 100644 (file)
index 0000000..ff7557b
--- /dev/null
@@ -0,0 +1,32 @@
+#ifndef ASYNCQUERYTASK_H
+#define ASYNCQUERYTASK_H
+
+#include "abstracttask.h"
+#include "sqlasyncqueryinternal.h"
+
+namespace LocalMyList {
+
+using namespace Internal;
+
+class AsyncQueryTask : public AbstractTask
+{
+       Q_OBJECT
+public:
+       explicit AsyncQueryTask(QObject *parent = 0);
+       ~AsyncQueryTask();
+
+       void setQuery(AsyncQuery *query);
+       Result *result() const;
+
+       QString taskSubject() const;
+       bool canUseThreads() const;
+
+       void start();
+private:
+       AsyncQuery *m_query;
+       Result *m_result;
+};
+
+} // namespace LocalMyList
+
+#endif // ASYNCQUERYTASK_H
diff --git a/localmylist/include/LocalMyList/SqlAsyncQuery b/localmylist/include/LocalMyList/SqlAsyncQuery
new file mode 100644 (file)
index 0000000..cb1ab36
--- /dev/null
@@ -0,0 +1 @@
+#include "../../sqlasyncquery.h"
index ea22659eca021c6f1a78513daea56c594fae39de..ba79b19b9ba79838873beb2655308026236d5ff1 100644 (file)
@@ -27,7 +27,10 @@ SOURCES += \
        scriptablesql.cpp \
        reportengine.cpp \
        databaseclasses.cpp \
-       sqlquery.cpp
+       sqlquery.cpp \
+       sqlasyncquery.cpp \
+       sqlasyncqueryinternal.cpp \
+       asyncquerytask.cpp
 
 HEADERS += \
        localmylist_global.h \
@@ -48,7 +51,10 @@ HEADERS += \
        scriptablesql.h \
        reportengine.h \
        databaseclasses.h \
-       sqlquery.h
+       sqlquery.h \
+       sqlasyncquery.h \
+       sqlasyncqueryinternal.h \
+       asyncquerytask.h
 
 CONV_HEADERS += \
        include/LocalMyList/AbstractTask \
diff --git a/localmylist/sqlasyncquery.cpp b/localmylist/sqlasyncquery.cpp
new file mode 100644 (file)
index 0000000..c09d4c1
--- /dev/null
@@ -0,0 +1,79 @@
+#include "sqlasyncquery.h"
+
+#include "sqlasyncqueryinternal.h"
+#include "asyncquerytask.h"
+
+namespace LocalMyList {
+
+using namespace Internal;
+
+SqlAsyncQuery::SqlAsyncQuery(QObject *parent) :
+       QObject(parent), d(new SqlAsyncQueryInternal(this))
+{
+}
+
+bool SqlAsyncQuery::prepare(const QString &query)
+{
+       return d->prepare(query);
+}
+
+void SqlAsyncQuery::bindValue(const QString &placeholder, const QVariant &val, QSql::ParamType paramType)
+{
+       d->bindValue(placeholder, val, paramType);
+}
+
+bool SqlAsyncQuery::exec()
+{
+       return d->exec();
+}
+
+bool SqlAsyncQuery::exec(const QString &query)
+{
+       return d->exec(query);
+}
+
+bool SqlAsyncQuery::next()
+{
+       return d->next();
+}
+
+QVariant SqlAsyncQuery::value(int index) const
+{
+       return d->value(index);
+}
+
+QVariant SqlAsyncQuery::value(const QString &name) const
+{
+       return d->value(name);
+}
+
+int SqlAsyncQuery::indexOf(const QString &name) const
+{
+       return d->indexOf(name);
+}
+
+void SqlAsyncQuery::finish()
+{
+       return d->finish();
+}
+
+QString SqlAsyncQuery::executedQuery() const
+{
+       return d->executedQuery();
+}
+
+QString SqlAsyncQuery::lastError() const
+{
+       return d->lastError();
+}
+
+void SqlAsyncQuery::resultRecieved()
+{
+       AsyncQueryTask *t = qobject_cast<AsyncQueryTask *>(sender());
+       if (!t)
+               return;
+
+       d->resultReady(t->result());
+}
+
+} // namespace LocalMyList
diff --git a/localmylist/sqlasyncquery.h b/localmylist/sqlasyncquery.h
new file mode 100644 (file)
index 0000000..1381357
--- /dev/null
@@ -0,0 +1,47 @@
+#ifndef SQLASYNCQUERY_H
+#define SQLASYNCQUERY_H
+
+#include "localmylist_global.h"
+#include <QObject>
+#include <QSql>
+
+namespace LocalMyList {
+
+namespace Internal {
+       class SqlAsyncQueryInternal;
+}
+class LOCALMYLISTSHARED_EXPORT SqlAsyncQuery : public QObject
+{
+       Q_OBJECT
+public:
+       explicit SqlAsyncQuery(QObject *parent = 0);
+
+       bool prepare(const QString &query);
+       void bindValue(const QString &placeholder, const QVariant &val, QSql::ParamType paramType = QSql::In);
+       bool exec();
+
+       bool exec(const QString &query);
+
+       bool next();
+       QVariant value(int index) const;
+       QVariant value(const QString &name) const;
+       int indexOf(const QString &name ) const;
+       void finish();
+
+       QString executedQuery() const;
+       QString lastError() const;
+
+signals:
+       void resultReady();
+
+private slots:
+       void resultRecieved();
+
+private:
+       Internal::SqlAsyncQueryInternal *d;
+};
+
+} // namespace LocalMyList
+
+
+#endif // SQLASYNCQUERY_H
diff --git a/localmylist/sqlasyncqueryinternal.cpp b/localmylist/sqlasyncqueryinternal.cpp
new file mode 100644 (file)
index 0000000..f4419c3
--- /dev/null
@@ -0,0 +1,166 @@
+#include "sqlasyncqueryinternal.h"
+
+#include <QObject>
+#include "sqlasyncquery.h"
+#include "asyncquerytask.h"
+#include "mylist.h"
+
+namespace LocalMyList {
+namespace Internal {
+
+SqlAsyncQueryInternal::SqlAsyncQueryInternal(SqlAsyncQuery *p_)
+       : p(p_), q(0), result(0), currentRow(-1), working(false)
+{
+}
+
+SqlAsyncQueryInternal::~SqlAsyncQueryInternal()
+{
+       if (q)
+               delete q;
+       if (result)
+               delete result;
+}
+
+bool SqlAsyncQueryInternal::prepare(const QString &query)
+{
+       if (working)
+       {
+               m_lastError = QObject::tr("Can not prepare new query while waiting for result");
+               return false;
+       }
+
+       if (q)
+               delete q;
+
+       q = new AsyncQuery;
+
+       q->query = query;
+       return true;
+}
+
+void SqlAsyncQueryInternal::bindValue(const QString &placeholder, const QVariant &val, QSql::ParamType paramType)
+{
+       if (working)
+               return;
+       if (!q)
+               return;
+
+       BoundValue b;
+       b.name = placeholder;
+       b.value = val;
+       b.paramType = paramType;
+
+       q->boundValues << b;
+}
+
+bool SqlAsyncQueryInternal::exec()
+{
+       if (working)
+               return false;
+
+       working = true;
+
+       AsyncQueryTask *task = new AsyncQueryTask;
+       task->setQuery(q);
+       QObject::connect(task, SIGNAL(finished()), p, SLOT(resultRecieved()));
+
+       MyList::instance()->executeTask(task);
+       return true;
+}
+
+bool SqlAsyncQueryInternal::exec(const QString &query)
+{
+       if (!prepare(query))
+               return false;
+       return exec();
+}
+
+bool SqlAsyncQueryInternal::next()
+{
+       if (!result)
+               return false;
+       if (currentRow == -2)
+               return false;
+
+       ++currentRow;
+       bool ret = currentRow < result->rows.count();
+
+       if (!ret)
+               currentRow = -2;
+
+       return ret;
+}
+
+QVariant SqlAsyncQueryInternal::value(int index) const
+{
+       if (!result)
+               return QVariant();
+       if (currentRow < 0)
+               return QVariant();
+       if (index < 0 || index >= result->rows.at(currentRow).count())
+               return QVariant();
+
+       return result->rows.at(currentRow).at(index).value;
+}
+
+QVariant SqlAsyncQueryInternal::value(const QString &name) const
+{
+       return value(indexOf(name));
+}
+
+int SqlAsyncQueryInternal::indexOf(const QString &name) const
+{
+       if (!result)
+               return -1;
+       if (currentRow < 0)
+               return -1;
+
+       int idx = -1;
+       for (int i = 0; i < result->rows.at(currentRow).count(); ++i)
+       {
+               if (result->rows.at(currentRow).at(i).name == name)
+               {
+                       idx = i;
+                       break;
+               }
+       }
+       return idx;
+}
+
+void SqlAsyncQueryInternal::finish()
+{
+       if (working)
+               return;
+
+       if (result)
+               delete result;
+       currentRow = -1;
+}
+
+QString SqlAsyncQueryInternal::executedQuery() const
+{
+       if (!q)
+               return QString();
+
+       return q->query;
+}
+
+QString SqlAsyncQueryInternal::lastError() const
+{
+       return m_lastError;
+}
+
+void SqlAsyncQueryInternal::resultReady(Result *newResult)
+{
+       if (result)
+               delete result;
+       result = newResult;
+       currentRow = -1;
+       working = false;
+}
+
+} // namespace Internal
+} // namespace LocalMyList
+
+
+
diff --git a/localmylist/sqlasyncqueryinternal.h b/localmylist/sqlasyncqueryinternal.h
new file mode 100644 (file)
index 0000000..596cfdc
--- /dev/null
@@ -0,0 +1,81 @@
+#ifndef SQLASYNCQUERYINTERNAL_H
+#define SQLASYNCQUERYINTERNAL_H
+
+#include <QString>
+#include <QVariant>
+#include <QSql>
+#include <QVector>
+
+namespace LocalMyList {
+
+class SqlAsyncQuery;
+
+namespace Internal {
+
+struct BoundValue
+{
+       QString name;
+       QVariant value;
+       QSql::ParamType paramType;
+};
+
+typedef QList<BoundValue> BoundValues;
+
+struct AsyncQuery
+{
+       QString query;
+       BoundValues boundValues;
+};
+
+struct Field
+{
+       QString name;
+       QVariant value;
+};
+
+typedef QVector<Field> Row;
+
+struct Result
+{
+       QList<Row> rows;
+       QString error;
+};
+
+
+class SqlAsyncQueryInternal
+{
+public:
+       SqlAsyncQueryInternal(SqlAsyncQuery *p_);
+       ~SqlAsyncQueryInternal();
+
+       bool prepare(const QString &query);
+       void bindValue(const QString &placeholder, const QVariant &val, QSql::ParamType paramType = QSql::In);
+       bool exec();
+
+       bool exec(const QString &query);
+
+       bool next();
+       QVariant value(int index) const;
+       QVariant value(const QString &name) const;
+       int indexOf(const QString &name) const;
+       void finish();
+
+       QString executedQuery() const;
+       QString lastError() const;
+
+       void resultReady(Result *newResult);
+
+       SqlAsyncQuery *p;
+       AsyncQuery *q;
+       Result *result;
+       int currentRow;
+
+       bool working;
+
+       QString m_lastError;
+};
+
+} // namespace Internal
+} // namespace LocalMyList
+
+#endif // SQLASYNCQUERYINTERNAL_H