--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#include "../../sqlasyncquery.h"
scriptablesql.cpp \
reportengine.cpp \
databaseclasses.cpp \
- sqlquery.cpp
+ sqlquery.cpp \
+ sqlasyncquery.cpp \
+ sqlasyncqueryinternal.cpp \
+ asyncquerytask.cpp
HEADERS += \
localmylist_global.h \
scriptablesql.h \
reportengine.h \
databaseclasses.h \
- sqlquery.h
+ sqlquery.h \
+ sqlasyncquery.h \
+ sqlasyncqueryinternal.h \
+ asyncquerytask.h
CONV_HEADERS += \
include/LocalMyList/AbstractTask \
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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
+
+
+
--- /dev/null
+#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