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>
|
|
|
|
|
|
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
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
|
class NUT_EXPORT Query : public QueryBase
|
|
|
|
|
{
|
2016-06-05 20:22:26 +08:00
|
|
|
QueryPrivate *d_ptr;
|
|
|
|
|
Q_DECLARE_PRIVATE(Query)
|
|
|
|
|
|
2016-05-12 14:08:58 +08:00
|
|
|
public:
|
|
|
|
|
Query(Database *database, TableSetBase *tableSet);
|
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
|
|
|
QList<T *> toList(int count = -1);
|
2016-06-05 20:22:26 +08:00
|
|
|
int remove();
|
2016-05-12 14:08:58 +08:00
|
|
|
T *first();
|
2016-06-05 20:22:26 +08:00
|
|
|
|
2016-05-12 14:08:58 +08:00
|
|
|
int count();
|
2016-06-05 20:22:26 +08:00
|
|
|
|
2017-05-25 23:46:54 +08:00
|
|
|
QVariant max(FieldPhrase<int> &f);
|
|
|
|
|
QVariant min(FieldPhrase<int> &f);
|
|
|
|
|
QVariant average(FieldPhrase<int> &f){
|
2016-06-05 20:22:26 +08:00
|
|
|
//TODO: ...
|
|
|
|
|
return QVariant();
|
|
|
|
|
}
|
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
|
|
|
|
|
|
|
|
Query<T> *join(Table *c){
|
|
|
|
|
join(c->metaObject()->className());
|
|
|
|
|
return this;
|
|
|
|
|
}
|
|
|
|
|
|
2016-05-21 16:09:03 +08:00
|
|
|
// Query<T> *setWhere(const QString &where);
|
2016-05-12 14:08:58 +08:00
|
|
|
Query<T> *orderBy(QString fieldName, QString type);
|
2016-06-05 20:22:26 +08:00
|
|
|
Query<T> *orderBy(WherePhrase phrase);
|
2016-05-12 14:08:58 +08:00
|
|
|
};
|
|
|
|
|
|
2017-02-01 18:01:21 +08:00
|
|
|
template <typename T>
|
|
|
|
|
inline Query<T> *createQuery(TableSet<T> *tableSet){
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2016-05-12 14:08:58 +08:00
|
|
|
template<class T>
|
2016-06-05 20:22:26 +08:00
|
|
|
Q_OUTOFLINE_TEMPLATE Query<T>::Query(Database *database, TableSetBase *tableSet) : QueryBase(database),
|
|
|
|
|
d_ptr(new QueryPrivate(this))
|
|
|
|
|
{
|
|
|
|
|
Q_D(Query);
|
|
|
|
|
|
|
|
|
|
d->database = database;
|
|
|
|
|
d->tableSet = tableSet;
|
2017-02-01 18:01:21 +08:00
|
|
|
d->tableName = TableModel::findByClassName(T::staticMetaObject.className())->name();
|
|
|
|
|
//d->database->tableName(T::staticMetaObject.className());
|
2016-06-05 20:22:26 +08:00
|
|
|
}
|
2016-05-12 14:08:58 +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);
|
|
|
|
|
delete d;
|
2016-05-12 14:08:58 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
|
Q_OUTOFLINE_TEMPLATE QList<T *> Query<T>::toList(int count)
|
|
|
|
|
{
|
2016-06-05 20:22:26 +08:00
|
|
|
Q_D(Query);
|
2016-05-12 14:08:58 +08:00
|
|
|
QList<T*> result;
|
2016-06-05 20:22:26 +08:00
|
|
|
d->select = "*";
|
|
|
|
|
|
|
|
|
|
// QSqlQuery q = d->database->exec(d->database->sqlGenertor()->selectCommand(d->wheres, d->orders, d->tableName, d->joinClassName));
|
|
|
|
|
QSqlQuery q = d->database->exec(d->database->sqlGenertor()->selectCommand(
|
|
|
|
|
SqlGeneratorBase::SelectALl,
|
|
|
|
|
"",
|
|
|
|
|
d->wheres,
|
|
|
|
|
d->orderPhrases,
|
|
|
|
|
d->tableName,
|
|
|
|
|
d->joinClassName));
|
|
|
|
|
|
2017-02-01 18:01:21 +08:00
|
|
|
QString pk = d->database->model().model(d->tableName)->primaryKey();
|
2016-05-12 14:08:58 +08:00
|
|
|
QVariant lastPkValue = QVariant();
|
|
|
|
|
int childTypeId = 0;
|
|
|
|
|
T *lastRow = 0;
|
|
|
|
|
TableSetBase *childTableSet;
|
2016-06-05 20:22:26 +08:00
|
|
|
QStringList masterFields = d->database->model().model(d->tableName)->fieldsNames();
|
2016-05-12 14:08:58 +08:00
|
|
|
QStringList childFields;
|
2016-06-05 20:22:26 +08:00
|
|
|
if(!d->joinClassName.isNull())
|
|
|
|
|
if(d->database->model().modelByClass(d->joinClassName)){
|
|
|
|
|
childFields = d->database->model().modelByClass(d->joinClassName)->fieldsNames();
|
|
|
|
|
QString joinTableName = d->database->tableName(d->joinClassName);
|
|
|
|
|
childTypeId = d->database->model().model(joinTableName)->typeId();
|
|
|
|
|
}
|
2016-05-12 14:08:58 +08:00
|
|
|
|
|
|
|
|
while (q.next()) {
|
|
|
|
|
if(lastPkValue != q.value(pk)){
|
|
|
|
|
T *t = new T();
|
|
|
|
|
|
|
|
|
|
foreach (QString field, masterFields)
|
|
|
|
|
t->setProperty(field.toLatin1().data(), q.value(field));
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
result.append(t);
|
|
|
|
|
lastRow = t;
|
|
|
|
|
|
|
|
|
|
if(childTypeId){
|
|
|
|
|
QSet<TableSetBase*> tableSets = t->tableSets;
|
|
|
|
|
foreach (TableSetBase *ts, tableSets)
|
2016-06-05 20:22:26 +08:00
|
|
|
if(ts->childClassName() == d->joinClassName)
|
2016-05-12 14:08:58 +08:00
|
|
|
childTableSet = ts;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(childTypeId){
|
|
|
|
|
const QMetaObject *childMetaObject = QMetaType::metaObjectForType(childTypeId);
|
|
|
|
|
Table *childTable = qobject_cast<Table*>(childMetaObject->newInstance());
|
|
|
|
|
|
|
|
|
|
foreach (QString field, childFields)
|
|
|
|
|
childTable->setProperty(field.toLatin1().data(), q.value(field));
|
2017-02-01 18:01:21 +08:00
|
|
|
//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);
|
|
|
|
|
childTableSet->add(childTable);
|
|
|
|
|
}
|
|
|
|
|
lastPkValue = q.value(pk);
|
|
|
|
|
|
|
|
|
|
if(!--count)
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
deleteLater();
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
|
Q_OUTOFLINE_TEMPLATE T *Query<T>::first()
|
|
|
|
|
{
|
|
|
|
|
QList<T *> list = toList(1);
|
|
|
|
|
|
|
|
|
|
if(list.count())
|
|
|
|
|
return list.first();
|
|
|
|
|
else
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
|
Q_OUTOFLINE_TEMPLATE int Query<T>::count()
|
|
|
|
|
{
|
2016-06-05 20:22:26 +08:00
|
|
|
Q_D(Query);
|
|
|
|
|
|
|
|
|
|
d->select = "COUNT(*)";
|
|
|
|
|
QSqlQuery q = d->database->exec(d->database->sqlGenertor()->selectCommand("COUNT(*)", d->wheres, d->orders, d->tableName, d->joinClassName));
|
|
|
|
|
|
|
|
|
|
if(q.next())
|
|
|
|
|
return q.value(0).toInt();
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<class T>
|
2017-05-25 23:46:54 +08:00
|
|
|
Q_OUTOFLINE_TEMPLATE QVariant Query<T>::max(FieldPhrase<int> &f){
|
2016-06-05 20:22:26 +08:00
|
|
|
Q_D(Query);
|
|
|
|
|
|
|
|
|
|
QSqlQuery q = d->database->exec(d->database->sqlGenertor()->selectCommand("MAX(" + f.data()->text + ")", d->wheres, d->orders, d->tableName, d->joinClassName));
|
|
|
|
|
|
|
|
|
|
if(q.next())
|
|
|
|
|
return q.value(0).toInt();
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<class T>
|
2017-05-25 23:46:54 +08:00
|
|
|
Q_OUTOFLINE_TEMPLATE QVariant Query<T>::min(FieldPhrase<int> &f){
|
2016-06-05 20:22:26 +08:00
|
|
|
Q_D(Query);
|
|
|
|
|
|
|
|
|
|
QSqlQuery q = d->database->exec(d->database->sqlGenertor()->selectCommand("MIN(" + f.data()->text + ")", d->wheres, d->orders, d->tableName, d->joinClassName));
|
|
|
|
|
|
2016-05-12 14:08:58 +08:00
|
|
|
if(q.next())
|
|
|
|
|
return q.value(0).toInt();
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
|
Q_OUTOFLINE_TEMPLATE int Query<T>::remove()
|
|
|
|
|
{
|
2016-06-05 20:22:26 +08:00
|
|
|
Q_D(Query);
|
|
|
|
|
|
|
|
|
|
QString sql = d->database->sqlGenertor()->deleteCommand(d->wheres, d->tableName);
|
|
|
|
|
// d->_database->sqlGenertor()->deleteRecords(_tableName, queryText());
|
2016-05-21 16:09:03 +08:00
|
|
|
// sql = compileCommand(sql);
|
2016-06-05 20:22:26 +08:00
|
|
|
QSqlQuery q = d->database->exec(sql);
|
2016-05-12 14:08:58 +08:00
|
|
|
return q.numRowsAffected();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
|
Q_OUTOFLINE_TEMPLATE Query<T> *Query<T>::orderBy(QString fieldName, QString type)
|
|
|
|
|
{
|
2016-06-05 20:22:26 +08:00
|
|
|
Q_D(Query);
|
|
|
|
|
d->orders.insert(fieldName, type);
|
2016-05-12 14:08:58 +08:00
|
|
|
return this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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-02-01 18:01:21 +08:00
|
|
|
NUT_END_NAMESPACE
|
2016-05-12 14:08:58 +08:00
|
|
|
|
|
|
|
|
#endif // QUERY_H
|