Nut/src/query.h

413 lines
11 KiB
C
Raw Normal View History

2016-05-12 14:08:58 +08:00
/**************************************************************************
**
** This file is part of Nut project.
** https://github.com/HamedMasafi/Nut
**
** Nut is free software: you can redistribute it and/or modify
** it under the terms of the GNU Lesser General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** Nut is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public License
** along with Nut. If not, see <http://www.gnu.org/licenses/>.
**
**************************************************************************/
#ifndef QUERY_H
#define QUERY_H
#include <QtCore/QVariant>
#include <QtCore/QDebug>
#include <QtCore/QScopedPointer>
#include <QtCore/QRegularExpression>
2017-06-12 00:50:43 +08:00
#include <QtCore/QMetaObject>
2016-05-12 14:08:58 +08:00
2016-06-05 20:22:26 +08:00
#include "query_p.h"
2016-05-12 14:08:58 +08:00
#include "database.h"
#include "databasemodel.h"
#include "tablesetbase_p.h"
#include "sqlgeneratorbase_p.h"
#include "querybase_p.h"
2016-05-21 16:09:03 +08:00
#include "wherephrase.h"
2017-02-01 18:01:21 +08:00
#include "tablemodel.h"
2016-05-12 14:08:58 +08:00
2017-02-01 18:01:21 +08:00
NUT_BEGIN_NAMESPACE
2016-05-12 14:08:58 +08:00
2017-08-10 23:09:41 +08:00
template <class T>
2016-05-12 14:08:58 +08:00
class NUT_EXPORT Query : public QueryBase
{
2016-06-05 20:22:26 +08:00
QueryPrivate *d_ptr;
Q_DECLARE_PRIVATE(Query)
2017-06-01 00:10:35 +08:00
bool m_autoDelete;
2016-05-12 14:08:58 +08:00
public:
2017-06-01 00:10:35 +08:00
Query(Database *database, TableSetBase *tableSet, bool autoDelete);
2017-02-01 18:01:21 +08:00
2016-06-05 20:22:26 +08:00
~Query();
2016-05-21 16:09:03 +08:00
2016-05-12 14:08:58 +08:00
Query<T> *join(const QString &tableName);
2016-05-24 14:47:37 +08:00
Query<T> *setWhere(WherePhrase where);
2016-06-05 20:22:26 +08:00
2017-08-10 23:09:41 +08:00
Query<T> *join(Table *c)
{
2016-06-05 20:22:26 +08:00
join(c->metaObject()->className());
return this;
}
2017-08-10 23:09:41 +08:00
// Query<T> *orderBy(QString fieldName, QString type);
2017-08-24 23:35:23 +08:00
Query<T> *skip(int &n);
Query<T> *take(int &n);
2016-06-05 20:22:26 +08:00
Query<T> *orderBy(WherePhrase phrase);
2017-09-10 22:18:20 +08:00
Query<T> *include(TableSetBase *t);
Query<T> *include(Table *t);
2017-05-31 00:19:37 +08:00
2017-07-25 22:10:43 +08:00
int count();
QVariant max(FieldPhrase<int> &f);
QVariant min(FieldPhrase<int> &f);
QVariant average(FieldPhrase<int> &f);
T *first();
QList<T *> toList(int count = -1);
2017-08-10 23:09:41 +08:00
template <typename F>
2017-07-25 22:10:43 +08:00
QList<F> select(const FieldPhrase<F> f);
2017-05-31 00:19:37 +08:00
int update(WherePhrase phrase);
2017-06-01 00:10:35 +08:00
int remove();
2017-07-25 22:10:43 +08:00
QString sqlCommand() const;
2016-05-12 14:08:58 +08:00
};
2017-02-01 18:01:21 +08:00
template <typename T>
2017-08-10 23:09:41 +08:00
inline Query<T> *createQuery(TableSet<T> *tableSet)
{
2017-08-24 23:35:23 +08:00
return tableSet->query();
2017-02-01 18:01:21 +08:00
}
2017-08-10 23:09:41 +08:00
template <class T>
Q_OUTOFLINE_TEMPLATE Query<T>::Query(Database *database, TableSetBase *tableSet,
bool autoDelete)
: QueryBase(database), d_ptr(new QueryPrivate(this)),
m_autoDelete(autoDelete)
2016-06-05 20:22:26 +08:00
{
Q_D(Query);
d->database = database;
d->tableSet = tableSet;
2017-08-10 23:09:41 +08:00
d->tableName
= // TableModel::findByClassName(T::staticMetaObject.className())->name();
d->database->model()
.tableByClassName(T::staticMetaObject.className())
->name();
2016-06-05 20:22:26 +08:00
}
2016-05-12 14:08:58 +08:00
2017-08-10 23:09:41 +08:00
template <class T>
2016-06-05 20:22:26 +08:00
Q_OUTOFLINE_TEMPLATE Query<T>::~Query()
2016-05-12 14:08:58 +08:00
{
2016-06-05 20:22:26 +08:00
Q_D(Query);
2017-06-01 23:38:53 +08:00
2016-06-05 20:22:26 +08:00
delete d;
2016-05-12 14:08:58 +08:00
}
2017-08-10 23:09:41 +08:00
template <class T>
2016-05-12 14:08:58 +08:00
Q_OUTOFLINE_TEMPLATE QList<T *> Query<T>::toList(int count)
{
2016-06-05 20:22:26 +08:00
Q_D(Query);
2017-08-10 23:09:41 +08:00
QList<T *> result;
2016-06-05 20:22:26 +08:00
d->select = "*";
2017-08-10 23:09:41 +08:00
// QSqlQuery q =
// d->database->exec(d->database->sqlGenertor()->selectCommand(d->wheres,
// d->orders, d->tableName, d->joinClassName));
2017-07-25 22:10:43 +08:00
d->sql = d->database->sqlGenertor()->selectCommand(
2017-08-10 23:09:41 +08:00
SqlGeneratorBase::SelectAll, "", d->wheres, d->orderPhrases,
2017-08-24 23:35:23 +08:00
d->tableName, d->joinClassName, d->skip, d->take);
2017-07-25 22:10:43 +08:00
QSqlQuery q = d->database->exec(d->sql);
2017-08-10 23:09:41 +08:00
// QString pk = TableModel::findByName(d->tableName)->primaryKey();
QString pk = d->database->model().tableByName(d->tableName)->primaryKey();
2016-05-12 14:08:58 +08:00
QVariant lastPkValue = QVariant();
int childTypeId = 0;
T *lastRow = 0;
2017-07-24 16:27:52 +08:00
TableSetBase *childTableSet = Q_NULLPTR;
2017-05-28 23:08:59 +08:00
2017-08-10 23:09:41 +08:00
// FIXME: getting table error
// QStringList masterFields =
// TableModel::findByName(d->tableName)->fieldsNames();
QStringList masterFields
= d->database->model().tableByName(d->tableName)->fieldsNames();
2016-05-12 14:08:58 +08:00
QStringList childFields;
2017-08-10 23:09:41 +08:00
if (!d->joinClassName.isNull()) {
TableModel *joinTableModel
= TableModel::findByClassName(d->joinClassName);
if (joinTableModel) {
// childFields =
// d->database->model().modelByClass(d->joinClassName)->fieldsNames();
childFields
= TableModel::findByClassName(d->joinClassName)->fieldsNames();
2016-06-05 20:22:26 +08:00
QString joinTableName = d->database->tableName(d->joinClassName);
2017-08-10 23:09:41 +08:00
childTypeId = d->database->model().tableByName(joinTableName)->typeId();
// childTypeId =
// TableModel::findByName(joinTableName)->typeId();
2016-06-05 20:22:26 +08:00
}
}
2016-05-12 14:08:58 +08:00
while (q.next()) {
2017-08-10 23:09:41 +08:00
if (lastPkValue != q.value(pk)) {
2016-05-12 14:08:58 +08:00
T *t = new T();
foreach (QString field, masterFields)
t->setProperty(field.toLatin1().data(), q.value(field));
2017-08-10 23:09:41 +08:00
// for (int i = 0; i < t->metaObject()->propertyCount();
// i++) {
// const QMetaProperty p =
// t->metaObject()->property(i);
2017-06-12 00:50:43 +08:00
2017-08-10 23:09:41 +08:00
// p.write(t,
// d->database->sqlGenertor()->readValue(p.type(),
// q.value(p.name())));
// }
2016-05-12 14:08:58 +08:00
2016-06-05 20:22:26 +08:00
t->setTableSet(d->tableSet);
2016-05-12 14:08:58 +08:00
t->setStatus(Table::FeatchedFromDB);
t->setParent(this);
2017-06-05 00:04:17 +08:00
t->clear();
2016-05-12 14:08:58 +08:00
result.append(t);
lastRow = t;
2017-08-10 23:09:41 +08:00
if (childTypeId) {
QSet<TableSetBase *> tableSets = t->tableSets;
2016-05-12 14:08:58 +08:00
foreach (TableSetBase *ts, tableSets)
2017-08-10 23:09:41 +08:00
if (ts->childClassName() == d->joinClassName)
2016-05-12 14:08:58 +08:00
childTableSet = ts;
}
}
2017-08-10 23:09:41 +08:00
if (childTypeId) {
const QMetaObject *childMetaObject
= QMetaType::metaObjectForType(childTypeId);
Table *childTable
= qobject_cast<Table *>(childMetaObject->newInstance());
2016-05-12 14:08:58 +08:00
foreach (QString field, childFields)
2017-08-10 23:09:41 +08:00
childTable->setProperty(field.toLatin1().data(),
q.value(field));
// TODO: set database for table
2016-05-12 14:08:58 +08:00
childTable->setParent(this);
childTable->setParentTable(lastRow);
childTable->setStatus(Table::FeatchedFromDB);
childTable->setTableSet(childTableSet);
2017-06-05 00:04:17 +08:00
childTable->clear();
2016-05-12 14:08:58 +08:00
childTableSet->add(childTable);
}
lastPkValue = q.value(pk);
2017-08-10 23:09:41 +08:00
if (!--count)
2016-05-12 14:08:58 +08:00
break;
}
2017-08-10 23:09:41 +08:00
if (m_autoDelete)
2017-06-01 00:10:35 +08:00
deleteLater();
2016-05-12 14:08:58 +08:00
return result;
}
template <typename T>
template <typename F>
Q_OUTOFLINE_TEMPLATE QList<F> Query<T>::select(const FieldPhrase<F> f)
{
Q_D(Query);
QList<F> ret;
2017-07-25 22:10:43 +08:00
d->sql = d->database->sqlGenertor()->selectCommand(
2017-08-10 23:09:41 +08:00
SqlGeneratorBase::SignleField, f.data()->text, d->wheres,
2017-08-24 23:35:23 +08:00
d->orderPhrases, d->tableName, d->joinClassName, d->skip, d->take);
2017-08-17 00:17:12 +08:00
2017-07-25 22:10:43 +08:00
QSqlQuery q = d->database->exec(d->sql);
while (q.next()) {
2017-08-17 00:17:12 +08:00
QVariant v = q.value(0);
ret.append(v.value<F>());
}
2017-08-10 23:09:41 +08:00
if (m_autoDelete)
2017-06-01 00:10:35 +08:00
deleteLater();
return ret;
}
2017-08-10 23:09:41 +08:00
template <class T>
2016-05-12 14:08:58 +08:00
Q_OUTOFLINE_TEMPLATE T *Query<T>::first()
{
QList<T *> list = toList(1);
2017-08-10 23:09:41 +08:00
if (list.count())
2016-05-12 14:08:58 +08:00
return list.first();
else
return 0;
}
2017-08-10 23:09:41 +08:00
template <class T>
2016-05-12 14:08:58 +08:00
Q_OUTOFLINE_TEMPLATE int Query<T>::count()
{
2016-06-05 20:22:26 +08:00
Q_D(Query);
d->select = "COUNT(*)";
2017-08-10 23:09:41 +08:00
d->sql = d->database->sqlGenertor()->selectCommand(SqlGeneratorBase::Count,
QStringLiteral("*"), d->wheres, d->orderPhrases, d->tableName, d->joinClassName);
2017-07-25 22:10:43 +08:00
QSqlQuery q = d->database->exec(d->sql);
2016-06-05 20:22:26 +08:00
2017-08-10 23:09:41 +08:00
if (q.next())
2016-06-05 20:22:26 +08:00
return q.value(0).toInt();
return 0;
}
2017-08-10 23:09:41 +08:00
template <class T>
Q_OUTOFLINE_TEMPLATE QVariant Query<T>::max(FieldPhrase<int> &f)
{
2016-06-05 20:22:26 +08:00
Q_D(Query);
2017-08-10 23:09:41 +08:00
d->sql = d->database->sqlGenertor()->selectCommand(
SqlGeneratorBase::Max, f.data()->text, d->wheres, d->orderPhrases,
d->tableName, d->joinClassName);
2017-07-25 22:10:43 +08:00
QSqlQuery q = d->database->exec(d->sql);
2016-06-05 20:22:26 +08:00
2017-08-10 23:09:41 +08:00
if (q.next())
2016-06-05 20:22:26 +08:00
return q.value(0).toInt();
return 0;
}
2017-08-10 23:09:41 +08:00
template <class T>
Q_OUTOFLINE_TEMPLATE QVariant Query<T>::min(FieldPhrase<int> &f)
{
2016-06-05 20:22:26 +08:00
Q_D(Query);
2017-08-10 23:09:41 +08:00
d->sql = d->database->sqlGenertor()->selectCommand(
SqlGeneratorBase::Min, f.data()->text, d->wheres, d->orderPhrases,
d->tableName, d->joinClassName);
2017-07-25 22:10:43 +08:00
QSqlQuery q = d->database->exec(d->sql);
2016-06-05 20:22:26 +08:00
2017-08-10 23:09:41 +08:00
if (q.next())
2016-05-12 14:08:58 +08:00
return q.value(0).toInt();
return 0;
}
2017-08-10 23:09:41 +08:00
template <class T>
2017-05-28 23:08:59 +08:00
Q_OUTOFLINE_TEMPLATE QVariant Query<T>::average(FieldPhrase<int> &f)
{
Q_D(Query);
2017-08-10 23:09:41 +08:00
d->sql = d->database->sqlGenertor()->selectCommand(
SqlGeneratorBase::Average, f.data()->text, d->wheres, d->orderPhrases,
d->tableName, d->joinClassName);
2017-07-25 22:10:43 +08:00
QSqlQuery q = d->database->exec(d->sql);
2017-05-28 23:08:59 +08:00
2017-08-10 23:09:41 +08:00
if (q.next())
2017-05-28 23:08:59 +08:00
return q.value(0).toInt();
return 0;
}
2017-08-10 23:09:41 +08:00
template <class T>
2016-05-12 14:08:58 +08:00
Q_OUTOFLINE_TEMPLATE Query<T> *Query<T>::join(const QString &tableName)
{
2016-06-05 20:22:26 +08:00
Q_D(Query);
d->joinClassName = tableName;
2016-05-12 14:08:58 +08:00
return this;
}
2017-08-10 23:09:41 +08:00
template <class T>
2016-05-24 14:47:37 +08:00
Q_OUTOFLINE_TEMPLATE Query<T> *Query<T>::setWhere(WherePhrase where)
2016-05-12 14:08:58 +08:00
{
2016-06-05 20:22:26 +08:00
Q_D(Query);
d->wheres.append(where);
2016-05-12 14:08:58 +08:00
return this;
}
2017-08-24 23:35:23 +08:00
template<class T>
Q_OUTOFLINE_TEMPLATE Query<T> *Query<T>::skip(int &n)
{
Q_D(Query);
d->skip = n;
return this;
}
template<class T>
Q_OUTOFLINE_TEMPLATE Query<T> *Query<T>::take(int &n)
{
Q_D(Query);
d->take = n;
return this;
}
2017-08-10 23:09:41 +08:00
//template <class T>
//Q_OUTOFLINE_TEMPLATE Query<T> *Query<T>::orderBy(QString fieldName,
// QString type)
//{
// Q_D(Query);
// d->orderPhrases.append(fieldName, type);
// return this;
//}
2016-05-12 14:08:58 +08:00
2017-08-10 23:09:41 +08:00
template <class T>
2016-06-05 20:22:26 +08:00
Q_OUTOFLINE_TEMPLATE Query<T> *Query<T>::orderBy(WherePhrase phrase)
2016-05-12 14:08:58 +08:00
{
2016-06-05 20:22:26 +08:00
Q_D(Query);
d->orderPhrases.append(phrase);
return this;
2016-05-12 14:08:58 +08:00
}
2017-09-10 22:18:20 +08:00
template <class T>
Q_OUTOFLINE_TEMPLATE Query<T> *Query<T>::include(TableSetBase *t)
{
Q_D(Query);
d->joinClassName = t->childClassName();
return this;
}
template <class T>
Q_OUTOFLINE_TEMPLATE Query<T> *Query<T>::include(Table *t)
{
Q_D(Query);
d->joinClassName = t->metaObject()->className();
return this;
}
2017-08-10 23:09:41 +08:00
template <class T>
2017-05-31 00:19:37 +08:00
Q_OUTOFLINE_TEMPLATE int Query<T>::update(WherePhrase phrase)
{
Q_D(Query);
2017-08-10 23:09:41 +08:00
d->sql = d->database->sqlGenertor()->updateCommand(phrase, d->wheres,
d->tableName);
2017-07-25 22:10:43 +08:00
QSqlQuery q = d->database->exec(d->sql);
2017-06-01 00:10:35 +08:00
if (m_autoDelete)
deleteLater();
return q.numRowsAffected();
}
2017-08-10 23:09:41 +08:00
template <class T>
2017-06-01 00:10:35 +08:00
Q_OUTOFLINE_TEMPLATE int Query<T>::remove()
{
Q_D(Query);
2017-08-10 23:09:41 +08:00
d->sql = d->database->sqlGenertor()->deleteCommand(d->wheres, d->tableName);
2017-07-25 22:10:43 +08:00
QSqlQuery q = d->database->exec(d->sql);
if (m_autoDelete)
deleteLater();
2017-05-31 00:19:37 +08:00
return q.numRowsAffected();
}
2017-08-10 23:09:41 +08:00
template <class T>
2017-07-25 22:10:43 +08:00
Q_OUTOFLINE_TEMPLATE QString Query<T>::sqlCommand() const
{
Q_D(const Query);
return d->sql;
}
2017-02-01 18:01:21 +08:00
NUT_END_NAMESPACE
2016-05-12 14:08:58 +08:00
#endif // QUERY_H