Nut/src/nut/core/query.h

757 lines
20 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/>.
**
**************************************************************************/
2020-08-08 15:29:16 +08:00
#ifndef NUT_QUERY_H
#define NUT_QUERY_H
2016-05-12 14:08:58 +08:00
#include <QtCore/QVariant>
#include <QtCore/QDebug>
#include <QtCore/QScopedPointer>
#include <QtCore/QRegularExpression>
2017-06-12 00:50:43 +08:00
#include <QtCore/QMetaObject>
2018-01-13 23:59:55 +08:00
#include <QtSql/QSqlResult>
2018-01-15 22:18:49 +08:00
#include <QtSql/QSqlError>
2018-02-13 23:39:21 +08:00
#include <QtSql/QSqlQueryModel>
2019-06-18 21:40:40 +08:00
#include <QtSql/QSqlQuery>
#ifndef NUT_RAW_POINTER
2019-06-18 21:40:40 +08:00
#include <QtCore/QSharedPointer>
#endif
2016-05-12 14:08:58 +08:00
#include <QtNut/table.h>
2020-08-08 15:29:16 +08:00
#include <QtNut/database.h>
#include <QtNut/databasemodel.h>
#include <QtNut/abstracttableset.h>
#include <QtNut/abstractsqlgenerator.h>
#include <QtNut/phrase.h>
#include <QtNut/tablemodel.h>
#include <QtNut/sqlmodel.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
2020-08-10 14:42:06 +08:00
struct NUT_EXPORT QueryData {
QString sql;
QString className;
QString tableName;
QString select;
Database *database;
AbstractTableSet *tableSet;
QStringList joins;
QList<RelationModel*> relations;
int skip;
int take;
PhraseList orderPhrase, fieldPhrase;
ConditionalPhrase wherePhrase;
QueryData *clone() {
2020-08-10 15:51:43 +08:00
auto r = new QueryData;
r->sql = sql;
r->className = className;
r->tableName = tableName;
r->select = select;
r->database = database;
r->tableSet = tableSet;
r->joins = joins;
r->relations = relations;
r->skip = skip;
r->take = take;
r->orderPhrase = orderPhrase;
r->fieldPhrase = fieldPhrase;
r->wherePhrase = wherePhrase;
return r;
2020-08-10 14:42:06 +08:00
}
2020-08-10 21:19:21 +08:00
2020-08-10 21:34:26 +08:00
QueryData() : skip(0), take(0)
{ }
QueryData(Database *db) : database(db), skip(0), take(0)
2020-08-10 21:19:21 +08:00
{ }
2020-08-10 14:42:06 +08:00
};
2017-08-10 23:09:41 +08:00
template <class T>
2020-08-10 21:19:21 +08:00
class Query
2016-05-12 14:08:58 +08:00
{
2020-08-10 14:42:06 +08:00
QueryData *d;
2017-06-01 00:10:35 +08:00
2016-05-12 14:08:58 +08:00
public:
2020-08-10 21:19:21 +08:00
explicit Query(Database *database, AbstractTableSet *tableSet);
2020-08-10 14:42:06 +08:00
Query (const Query<T> &other);
Query (Query<T> &&other);
2016-06-05 20:22:26 +08:00
~Query();
2016-05-21 16:09:03 +08:00
2020-08-10 14:42:06 +08:00
Query<T>& operator=(const Query<T> &q);
2018-01-09 17:33:54 +08:00
//ddl
2016-06-05 20:22:26 +08:00
2020-08-10 14:42:06 +08:00
Query<T> &join(const QString &className);
Query<T> &join(Table *c);
2016-06-05 20:22:26 +08:00
2018-01-09 00:59:16 +08:00
template<class TABLE>
2020-08-10 14:42:06 +08:00
Query<T> &join()
2018-01-09 00:59:16 +08:00
{
join(TABLE::staticMetaObject.className());
2020-08-10 14:42:06 +08:00
return *this;
2018-01-09 00:59:16 +08:00
}
2020-08-10 14:42:06 +08:00
// Query<T> &orderBy(QString fieldName, QString type);
Query<T> &skip(int n);
Query<T> &take(int n);
Query<T> &fields(const PhraseList &ph);
Query<T> &orderBy(const PhraseList &ph);
Query<T> &where(const ConditionalPhrase &ph);
Query<T> &setWhere(const ConditionalPhrase &ph);
2018-02-17 23:44:39 +08:00
2018-01-09 17:33:54 +08:00
//data selecting
2019-06-18 23:37:03 +08:00
Row<T> first();
RowList<T> toList(int count = -1);
2018-01-09 17:33:54 +08:00
template <typename F>
QList<F> select(const FieldPhrase<F> f);
2019-06-08 16:40:00 +08:00
template<typename O>
QList<O> select(const std::function<O(const QSqlQuery &q)> allocator);
2017-07-25 22:10:43 +08:00
int count();
2018-01-16 04:04:42 +08:00
QVariant max(const FieldPhrase<int> &f);
QVariant min(const FieldPhrase<int> &f);
QVariant sum(const FieldPhrase<int> &f);
2018-01-16 04:04:42 +08:00
QVariant average(const FieldPhrase<int> &f);
2017-07-25 22:10:43 +08:00
2018-10-15 22:34:50 +08:00
2018-01-09 17:33:54 +08:00
//data mailpulation
2018-02-17 23:44:39 +08:00
int update(const AssignmentPhraseList &ph);
QVariant insert(const AssignmentPhraseList &p);
2017-06-01 00:10:35 +08:00
int remove();
2017-07-25 22:10:43 +08:00
2018-10-15 22:34:50 +08:00
QSqlQueryModel *toModel();
void toModel(QSqlQueryModel *model);
2019-06-18 21:40:40 +08:00
void toModel(SqlModel *model);
2018-02-13 23:39:21 +08:00
2018-01-09 17:33:54 +08:00
//debug purpose
2017-07-25 22:10:43 +08:00
QString sqlCommand() const;
2016-05-12 14:08:58 +08:00
};
2019-06-08 16:40:00 +08:00
template<typename T>
template<typename O>
Q_OUTOFLINE_TEMPLATE QList<O> Query<T>::select(const std::function<O (const QSqlQuery &)> allocator)
{
2020-08-10 14:42:06 +08:00
//Q_D(AbstractQuery);
2019-06-08 16:40:00 +08:00
QList<O> ret;
d->joins.prepend(d->tableName);
2020-07-30 23:05:11 +08:00
d->sql = d->database->sqlGenerator()->selectCommand(d->tableName,
2020-08-06 23:19:27 +08:00
AbstractSqlGenerator::SingleField,
2020-07-30 23:05:11 +08:00
QStringLiteral("*"),
d->wherePhrase,
d->relations,
d->skip,
d->take);
2019-06-08 16:40:00 +08:00
QSqlQuery q = d->database->exec(d->sql);
while (q.next()) {
O obj = allocator(q);
ret.append(obj);
}
return ret;
}
2019-06-07 16:19:20 +08:00
//template <typename T>
2020-08-10 14:42:06 +08:00
//inline Query<T> &createQuery(TableSet<T> *tableSet)
2019-06-07 16:19:20 +08:00
//{
// return tableSet->query();
//}
2017-02-01 18:01:21 +08:00
2017-08-10 23:09:41 +08:00
template <class T>
2020-08-10 21:19:21 +08:00
Q_OUTOFLINE_TEMPLATE Query<T>::Query(Database *database, AbstractTableSet *tableSet)
: d(new QueryData(database))
2016-06-05 20:22:26 +08:00
{
2020-08-10 14:42:06 +08:00
//Q_D(AbstractQuery);
2016-06-05 20:22:26 +08:00
d->database = database;
d->tableSet = tableSet;
2020-07-30 23:05:11 +08:00
d->className = QString::fromUtf8(T::staticMetaObject.className());
2018-01-15 22:18:49 +08:00
d->tableName =
2018-01-13 23:59:55 +08:00
d->database->model()
.tableByClassName(d->className)
2017-08-10 23:09:41 +08:00
->name();
2016-06-05 20:22:26 +08:00
}
2016-05-12 14:08:58 +08:00
2020-08-10 14:42:06 +08:00
template<class T>
2020-08-10 21:19:21 +08:00
Q_OUTOFLINE_TEMPLATE Query<T>::Query(const Query<T> &other) {
2020-08-10 14:42:06 +08:00
d = other.d->clone();
}
template<class T>
2020-08-10 21:19:21 +08:00
Q_OUTOFLINE_TEMPLATE Query<T>::Query(Query<T> &&other) {
2020-08-10 14:42:06 +08:00
d = std::move(other.d);
2020-08-10 15:51:43 +08:00
other.d = nullptr;
2020-08-10 14:42:06 +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
{
2020-08-10 14:42:06 +08:00
//Q_D(AbstractQuery);
2016-06-05 20:22:26 +08:00
delete d;
2016-05-12 14:08:58 +08:00
}
2020-08-10 14:42:06 +08:00
template<class T>
Q_OUTOFLINE_TEMPLATE Query<T> &Query<T>::operator=(const Query<T> &q)
{
if (this != &q)
{
2020-08-10 15:51:43 +08:00
QueryData *p = q.d ? q.d->clone() : nullptr;
2020-08-10 14:42:06 +08:00
delete d;
d = p;
}
return *this;
}
2017-08-10 23:09:41 +08:00
template <class T>
2019-06-18 23:37:03 +08:00
Q_OUTOFLINE_TEMPLATE RowList<T> Query<T>::toList(int count)
2016-05-12 14:08:58 +08:00
{
2020-08-10 14:42:06 +08:00
//Q_D(AbstractQuery);
2019-06-18 23:37:03 +08:00
RowList<T> returnList;
2020-07-29 22:11:19 +08:00
d->select = QStringLiteral("*");
2018-01-11 17:36:48 +08:00
2020-04-28 21:47:25 +08:00
d->sql = d->database->sqlGenerator()->selectCommand(
2018-02-17 23:44:39 +08:00
d->tableName, d->fieldPhrase, d->wherePhrase, d->orderPhrase,
d->relations, d->skip, count);
2019-06-19 17:24:58 +08:00
2017-07-25 22:10:43 +08:00
QSqlQuery q = d->database->exec(d->sql);
2018-01-14 22:03:24 +08:00
if (q.lastError().isValid()) {
qDebug() << q.lastError().text();
2018-01-14 22:03:24 +08:00
return returnList;
}
2018-01-15 06:12:46 +08:00
QSet<TableModel*> relatedTables;
relatedTables << d->database->model().tableByName(d->tableName);
2021-03-14 16:42:04 +08:00
Q_FOREACH (RelationModel *rel, d->relations)
2018-01-15 06:12:46 +08:00
relatedTables << rel->slaveTable << rel->masterTable;
2018-01-11 17:36:48 +08:00
struct LevelData{
2018-01-13 23:59:55 +08:00
QList<int> masters;
QList<int> slaves;
2018-01-15 21:50:40 +08:00
QList<QString> masterFields;
2018-01-15 06:12:46 +08:00
QString keyFiledname;
QVariant lastKeyValue;
TableModel *table;
Row<Table> lastRow;
2018-01-11 17:36:48 +08:00
};
QVector<LevelData> levels;
2018-01-15 06:12:46 +08:00
QSet<QString> importedTables;
auto add_table = [&](int i, TableModel* table) {
if (importedTables.contains(table->name()))
return;
importedTables.insert(table->name());
2018-01-13 23:59:55 +08:00
2018-01-11 17:36:48 +08:00
LevelData data;
2018-01-15 06:12:46 +08:00
data.table = table;
2020-07-30 23:05:11 +08:00
data.keyFiledname = data.table->name()
+ QStringLiteral(".")
+ data.table->primaryKey();
2018-01-15 06:12:46 +08:00
data.lastKeyValue = QVariant();
2018-01-15 21:50:40 +08:00
QHash<QString, QString> masters;
2021-03-14 16:42:04 +08:00
Q_FOREACH (RelationModel *rel, d->relations)
2018-01-15 06:12:46 +08:00
if (rel->slaveTable->name() == table->name())
2018-01-15 21:50:40 +08:00
masters.insert(rel->masterTable->name(), rel->localProperty);
2018-01-15 06:12:46 +08:00
for (int j = 0; j < levels.count(); ++j) {
LevelData &dt = levels[j];
2018-01-15 21:50:40 +08:00
QHashIterator<QString, QString> it(masters);
while (it.hasNext()) {
it.next();
if (dt.table->name() == it.key()) {
2018-01-15 06:12:46 +08:00
data.masters.append(j);
2018-01-15 21:50:40 +08:00
data.masterFields.append(it.value());
2018-01-15 06:12:46 +08:00
dt.slaves.append(i);
}
2018-01-15 21:50:40 +08:00
}
2018-01-12 00:14:29 +08:00
}
2018-01-15 22:18:49 +08:00
2018-01-11 17:36:48 +08:00
levels.append(data);
2018-01-15 06:12:46 +08:00
};
for (int i = 0; i < d->relations.count(); ++i) {
RelationModel *rel = d->relations[i];
add_table(i, rel->masterTable);
add_table(i, rel->slaveTable);
}
2018-01-11 15:13:01 +08:00
2018-01-15 21:50:40 +08:00
if (!importedTables.count()) {
LevelData data;
data.table = d->database->model().tableByName(d->tableName);
2020-07-30 23:05:11 +08:00
data.keyFiledname = d->tableName + QStringLiteral(".") + data.table->primaryKey();
2018-01-15 21:50:40 +08:00
data.lastKeyValue = QVariant();
levels.append(data);
}
2018-01-15 06:12:46 +08:00
QVector<bool> checked;
checked.reserve(levels.count());
for (int i = 0; i < levels.count(); ++i)
checked.append(false);
2018-01-15 22:18:49 +08:00
2018-01-11 17:36:48 +08:00
while (q.next()) {
2018-01-15 06:12:46 +08:00
checked.fill(false);
2018-01-13 23:59:55 +08:00
int p = levels.count();
2018-01-15 06:12:46 +08:00
int n = -1;
2018-01-13 23:59:55 +08:00
while (p) {
// Q_ASSERT(p != lastP);
// if (p == lastP)
// qFatal("NULL Loop detected");
2018-10-15 22:34:50 +08:00
++n;
n = n % levels.count();
2018-01-15 06:12:46 +08:00
if (checked[n])
continue;
LevelData &data = levels[n];
// check if key value is changed
if (data.lastKeyValue == q.value(data.keyFiledname)) {
--p;
// qDebug() << "key os not changed for" << data.keyFiledname;
2018-01-15 06:12:46 +08:00
continue;
2018-01-11 17:36:48 +08:00
}
2018-01-15 06:12:46 +08:00
// check if master if current table has processed
2021-03-14 16:42:04 +08:00
Q_FOREACH (int m, data.masters)
2018-10-15 22:34:50 +08:00
if (!checked[m]) {
// qDebug() << "row is checked";
2018-01-15 06:12:46 +08:00
continue;
2018-10-15 22:34:50 +08:00
}
2018-01-15 06:12:46 +08:00
checked[n] = true;
--p;
data.lastKeyValue = q.value(data.keyFiledname);
//create table row
2019-07-21 15:11:34 +08:00
Row<Table> row;
2018-01-15 06:12:46 +08:00
if (data.table->className() == d->className) {
2019-07-21 15:11:34 +08:00
row = Nut::create<T>();
#ifdef NUT_RAW_POINTER
2019-07-18 15:38:16 +08:00
returnList.append(dynamic_cast<T*>(table));
#else
returnList.append(row.objectCast<T>());
2019-06-18 21:40:40 +08:00
#endif
2019-07-21 15:11:34 +08:00
d->tableSet->add(row);
2018-01-15 06:12:46 +08:00
} else {
2019-07-21 15:11:34 +08:00
Table *table;
2019-07-18 15:38:16 +08:00
const QMetaObject *childMetaObject
= QMetaType::metaObjectForType(data.table->typeId());
2019-07-18 15:09:31 +08:00
table = qobject_cast<Table *>(childMetaObject->newInstance());
2019-07-21 15:11:34 +08:00
// table = dynamic_cast<Table *>(QMetaType::create(data.table->typeId()));
2019-07-18 15:09:31 +08:00
if (!table)
2018-02-13 23:39:21 +08:00
qFatal("Could not create instance of %s",
qPrintable(data.table->name()));
2019-07-21 15:11:34 +08:00
row = createFrom(table);
2018-01-15 06:12:46 +08:00
}
2019-02-10 17:35:35 +08:00
QList<FieldModel*> childFields = data.table->fields();
2021-03-14 16:42:04 +08:00
Q_FOREACH (FieldModel *field, childFields)
2019-07-21 15:11:34 +08:00
row->setProperty(field->name.toLatin1().data(),
2020-04-28 21:47:25 +08:00
d->database->sqlGenerator()->unescapeValue(
2020-07-30 23:05:11 +08:00
field->type,
q.value(data.table->name() + QStringLiteral(".") + field->name)));
2018-01-15 06:12:46 +08:00
2018-01-15 21:50:40 +08:00
for (int i = 0; i < data.masters.count(); ++i) {
int master = data.masters[i];
auto tableset = levels[master].lastRow.data()->childTableSet(
data.table->className());
2019-07-21 15:11:34 +08:00
tableset->add(row);
2018-01-15 06:12:46 +08:00
}
row->setStatus(Table::FetchedFromDB);
2020-08-10 15:51:43 +08:00
// row->setParent(this);
2019-07-21 15:11:34 +08:00
row->clear();
2018-01-15 06:12:46 +08:00
//set last created row
data.lastRow = row;
2018-01-15 06:12:46 +08:00
} //while
} // while
2019-06-18 21:40:40 +08:00
2018-01-11 17:36:48 +08:00
return returnList;
2016-05-12 14:08:58 +08:00
}
template <typename T>
template <typename F>
Q_OUTOFLINE_TEMPLATE QList<F> Query<T>::select(const FieldPhrase<F> f)
{
2020-08-10 14:42:06 +08:00
//Q_D(AbstractQuery);
QList<F> ret;
2018-01-11 00:18:49 +08:00
d->joins.prepend(d->tableName);
2020-04-28 21:47:25 +08:00
d->sql = d->database->sqlGenerator()->selectCommand(
2018-02-17 23:44:39 +08:00
d->tableName,
2020-08-06 23:19:27 +08:00
AbstractSqlGenerator::SingleField, f.data->toString(),
2018-02-17 23:44:39 +08:00
d->wherePhrase,
d->relations,
d->skip, d->take);
2018-03-11 16:38:07 +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>());
}
return ret;
}
2017-08-10 23:09:41 +08:00
template <class T>
2019-06-18 23:37:03 +08:00
Q_OUTOFLINE_TEMPLATE Row<T> Query<T>::first()
2016-05-12 14:08:58 +08:00
{
2018-01-09 17:33:54 +08:00
skip(0);
2019-06-18 23:37:03 +08:00
RowList<T> list = toList(1);
2016-05-12 14:08:58 +08:00
2017-08-10 23:09:41 +08:00
if (list.count())
2016-05-12 14:08:58 +08:00
return list.first();
else
2018-10-15 22:34:50 +08:00
return nullptr;
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 int Query<T>::count()
{
2020-08-10 14:42:06 +08:00
//Q_D(AbstractQuery);
2016-06-05 20:22:26 +08:00
2018-01-11 00:18:49 +08:00
d->joins.prepend(d->tableName);
2020-08-01 16:57:18 +08:00
d->select = QStringLiteral("COUNT(*)");
2020-04-28 21:47:25 +08:00
d->sql = d->database->sqlGenerator()->selectCommand(
2018-02-17 23:44:39 +08:00
d->tableName,
2020-08-06 23:19:27 +08:00
AbstractSqlGenerator::Count,
2018-02-17 23:44:39 +08:00
QStringLiteral("*"),
d->wherePhrase,
d->relations);
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>
2018-01-16 04:04:42 +08:00
Q_OUTOFLINE_TEMPLATE QVariant Query<T>::max(const FieldPhrase<int> &f)
2017-08-10 23:09:41 +08:00
{
2020-08-10 14:42:06 +08:00
//Q_D(AbstractQuery);
2016-06-05 20:22:26 +08:00
2018-01-11 00:18:49 +08:00
d->joins.prepend(d->tableName);
2020-04-28 21:47:25 +08:00
d->sql = d->database->sqlGenerator()->selectCommand(
2018-02-17 23:44:39 +08:00
d->tableName,
2020-08-06 23:19:27 +08:00
AbstractSqlGenerator::Max, f.data->toString(),
2018-02-17 23:44:39 +08:00
d->wherePhrase,
2018-01-13 23:59:55 +08:00
d->relations);
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>
2018-01-16 04:04:42 +08:00
Q_OUTOFLINE_TEMPLATE QVariant Query<T>::min(const FieldPhrase<int> &f)
2017-08-10 23:09:41 +08:00
{
2020-08-10 14:42:06 +08:00
//Q_D(AbstractQuery);
2016-06-05 20:22:26 +08:00
2018-01-11 00:18:49 +08:00
d->joins.prepend(d->tableName);
2020-04-28 21:47:25 +08:00
d->sql = d->database->sqlGenerator()->selectCommand(
2018-02-17 23:44:39 +08:00
d->tableName,
2020-08-06 23:19:27 +08:00
AbstractSqlGenerator::Min, f.data->toString(),
2018-02-17 23:44:39 +08:00
d->wherePhrase,
2018-01-13 23:59:55 +08:00
d->relations);
2017-07-25 22:10:43 +08:00
QSqlQuery q = d->database->exec(d->sql);
2016-06-05 20:22:26 +08:00
if (q.next())
return q.value(0).toInt();
return 0;
}
template <class T>
Q_OUTOFLINE_TEMPLATE QVariant Query<T>::sum(const FieldPhrase<int> &f)
{
2020-08-10 14:42:06 +08:00
//Q_D(AbstractQuery);
d->joins.prepend(d->tableName);
2020-04-28 21:47:25 +08:00
d->sql = d->database->sqlGenerator()->selectCommand(
d->tableName,
2020-08-06 23:19:27 +08:00
AbstractSqlGenerator::Sum, f.data->toString(),
d->wherePhrase,
d->relations);
QSqlQuery q = d->database->exec(d->sql);
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>
2018-01-16 04:04:42 +08:00
Q_OUTOFLINE_TEMPLATE QVariant Query<T>::average(const FieldPhrase<int> &f)
2017-05-28 23:08:59 +08:00
{
2020-08-10 14:42:06 +08:00
//Q_D(AbstractQuery);
2017-05-28 23:08:59 +08:00
2018-01-11 00:18:49 +08:00
d->joins.prepend(d->tableName);
2020-04-28 21:47:25 +08:00
d->sql = d->database->sqlGenerator()->selectCommand(
2018-02-17 23:44:39 +08:00
d->tableName,
2020-08-06 23:19:27 +08:00
AbstractSqlGenerator::Average, f.data->toString(),
2018-02-17 23:44:39 +08:00
d->wherePhrase,
2018-01-13 23:59:55 +08:00
d->relations);
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;
}
2018-10-15 22:34:50 +08:00
template<class T>
Q_OUTOFLINE_TEMPLATE QVariant Query<T>::insert(const AssignmentPhraseList &p)
2018-10-15 22:34:50 +08:00
{
2020-08-10 14:42:06 +08:00
//Q_D(AbstractQuery);
2020-04-28 21:47:25 +08:00
d->sql = d->database->sqlGenerator()
2018-10-15 22:34:50 +08:00
->insertCommand(d->tableName, p);
QSqlQuery q = d->database->exec(d->sql);
return q.lastInsertId();
}
2017-08-10 23:09:41 +08:00
template <class T>
2020-08-10 14:42:06 +08:00
Q_OUTOFLINE_TEMPLATE Query<T> &Query<T>::join(const QString &className)
2016-05-12 14:08:58 +08:00
{
2020-08-10 14:42:06 +08:00
//Q_D(AbstractQuery);
2018-01-13 23:59:55 +08:00
2018-01-15 22:18:49 +08:00
RelationModel *rel = d->database->model()
.relationByClassNames(d->className, className);
2018-01-13 23:59:55 +08:00
if (!rel)
2018-01-15 22:18:49 +08:00
rel = d->database->model()
.relationByClassNames(className, d->className);
2018-01-13 23:59:55 +08:00
2018-01-14 22:03:24 +08:00
if (!rel) {
2018-02-26 18:28:01 +08:00
qDebug() << "No relation between" << d->className
2018-02-25 23:21:42 +08:00
<< "and" << className;
2020-08-10 14:42:06 +08:00
return *this;
2018-01-14 22:03:24 +08:00
}
2018-01-13 23:59:55 +08:00
d->relations.append(rel);
2018-01-10 01:32:28 +08:00
d->joins.append(className);
2020-08-10 14:42:06 +08:00
return *this;
2016-05-12 14:08:58 +08:00
}
2018-01-09 17:33:54 +08:00
template<class T>
2020-08-10 14:42:06 +08:00
Q_OUTOFLINE_TEMPLATE Query<T> &Query<T>::join(Table *c)
2018-01-09 17:33:54 +08:00
{
join(c->metaObject()->className());
2020-08-10 14:42:06 +08:00
return *this;
2018-01-09 17:33:54 +08:00
}
2017-08-10 23:09:41 +08:00
template <class T>
2020-08-10 14:42:06 +08:00
Q_OUTOFLINE_TEMPLATE Query<T> &Query<T>::where(const ConditionalPhrase &ph)
2018-02-17 23:44:39 +08:00
{
2020-08-10 14:42:06 +08:00
//Q_D(AbstractQuery);
2018-02-18 22:58:55 +08:00
if (d->wherePhrase.data)
d->wherePhrase = d->wherePhrase && ph;
else
d->wherePhrase = ph;
2020-08-10 14:42:06 +08:00
return *this;
2018-02-17 23:44:39 +08:00
}
template <class T>
2020-08-10 14:42:06 +08:00
Q_OUTOFLINE_TEMPLATE Query<T> &Query<T>::setWhere(const ConditionalPhrase &ph)
2016-05-12 14:08:58 +08:00
{
2020-08-10 14:42:06 +08:00
//Q_D(AbstractQuery);
2018-02-17 23:44:39 +08:00
d->wherePhrase = ph;
2020-08-10 14:42:06 +08:00
return *this;
2016-05-12 14:08:58 +08:00
}
2017-08-24 23:35:23 +08:00
template<class T>
2020-08-10 14:42:06 +08:00
Q_OUTOFLINE_TEMPLATE Query<T> &Query<T>::skip(int n)
2017-08-24 23:35:23 +08:00
{
2020-08-10 14:42:06 +08:00
//Q_D(AbstractQuery);
2017-08-24 23:35:23 +08:00
d->skip = n;
2020-08-10 14:42:06 +08:00
return *this;
2017-08-24 23:35:23 +08:00
}
template<class T>
2020-08-10 14:42:06 +08:00
Q_OUTOFLINE_TEMPLATE Query<T> &Query<T>::take(int n)
2017-08-24 23:35:23 +08:00
{
2020-08-10 14:42:06 +08:00
//Q_D(AbstractQuery);
2017-08-24 23:35:23 +08:00
d->take = n;
2020-08-10 14:42:06 +08:00
return *this;
2017-08-24 23:35:23 +08:00
}
2018-02-13 23:39:21 +08:00
template<class T>
2020-08-10 14:42:06 +08:00
Q_OUTOFLINE_TEMPLATE Query<T> &Query<T>::fields(const PhraseList &ph)
2018-02-13 23:39:21 +08:00
{
2020-08-10 14:42:06 +08:00
//Q_D(AbstractQuery);
2018-02-17 23:44:39 +08:00
d->fieldPhrase = ph;
2020-08-10 14:42:06 +08:00
return *this;
2018-02-13 23:39:21 +08:00
}
2017-08-10 23:09:41 +08:00
//template <class T>
2020-08-10 14:42:06 +08:00
//Q_OUTOFLINE_TEMPLATE Query<T> &Query<T>::orderBy(QString fieldName,
2017-08-10 23:09:41 +08:00
// QString type)
//{
2020-08-10 14:42:06 +08:00
// //Q_D(AbstractQuery);
2017-08-10 23:09:41 +08:00
// d->orderPhrases.append(fieldName, type);
2020-08-10 14:42:06 +08:00
// return *this;
2017-08-10 23:09:41 +08:00
//}
2016-05-12 14:08:58 +08:00
2017-08-10 23:09:41 +08:00
template <class T>
2020-08-10 14:42:06 +08:00
Q_OUTOFLINE_TEMPLATE Query<T> &Query<T>::orderBy(const PhraseList &ph)
2016-05-12 14:08:58 +08:00
{
2020-08-10 14:42:06 +08:00
//Q_D(AbstractQuery);
2018-02-17 23:44:39 +08:00
d->orderPhrase = ph;
2020-08-10 14:42:06 +08:00
return *this;
2016-05-12 14:08:58 +08:00
}
2017-08-10 23:09:41 +08:00
template <class T>
2018-02-17 23:44:39 +08:00
Q_OUTOFLINE_TEMPLATE int Query<T>::update(const AssignmentPhraseList &ph)
2017-05-31 00:19:37 +08:00
{
2020-08-10 14:42:06 +08:00
//Q_D(AbstractQuery);
2017-05-31 00:19:37 +08:00
2020-04-28 21:47:25 +08:00
d->sql = d->database->sqlGenerator()->updateCommand(
2018-02-17 23:44:39 +08:00
d->tableName,
ph,
d->wherePhrase);
2019-04-09 15:25:19 +08:00
2017-07-25 22:10:43 +08:00
QSqlQuery q = d->database->exec(d->sql);
2018-03-11 16:38:07 +08:00
2017-06-01 00:10:35 +08:00
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()
{
2020-08-10 14:42:06 +08:00
//Q_D(AbstractQuery);
2017-06-01 00:10:35 +08:00
2020-04-28 21:47:25 +08:00
d->sql = d->database->sqlGenerator()->deleteCommand(
2018-02-17 23:44:39 +08:00
d->tableName, d->wherePhrase);
2017-07-25 22:10:43 +08:00
QSqlQuery q = d->database->exec(d->sql);
2017-05-31 00:19:37 +08:00
return q.numRowsAffected();
}
2018-02-13 23:39:21 +08:00
template <class T>
2018-10-15 22:34:50 +08:00
Q_OUTOFLINE_TEMPLATE QSqlQueryModel *Query<T>::toModel()
{
QSqlQueryModel *model = new QSqlQueryModel;
toModel(model);
return model;
}
template <class T>
Q_OUTOFLINE_TEMPLATE void Query<T>::toModel(QSqlQueryModel *model)
2018-02-13 23:39:21 +08:00
{
2020-08-10 14:42:06 +08:00
//Q_D(AbstractQuery);
2018-02-18 22:58:55 +08:00
2020-04-28 21:47:25 +08:00
d->sql = d->database->sqlGenerator()->selectCommand(
2018-02-18 22:58:55 +08:00
d->tableName,
d->fieldPhrase,
d->wherePhrase, d->orderPhrase, d->relations,
d->skip, d->take);
2019-02-10 17:35:35 +08:00
2018-02-18 22:58:55 +08:00
DatabaseModel dbModel = d->database->model();
model->setQuery(d->sql, d->database->database());
int fieldIndex = 0;
2018-10-15 22:34:50 +08:00
if (d->fieldPhrase.data.count()) {
2021-03-14 16:42:04 +08:00
Q_FOREACH (const PhraseData *pd, d->fieldPhrase.data) {
2020-07-29 22:11:19 +08:00
QString displayName = dbModel
.tableByClassName(QString::fromUtf8(pd->className))
->field(QString::fromUtf8(pd->fieldName))
->displayName;
2018-10-15 22:34:50 +08:00
model->setHeaderData(fieldIndex++,
Qt::Horizontal,
displayName);
}
} else {
TableModel *tbl = d->database->model().tableByName(d->tableName);
2021-03-14 16:42:04 +08:00
Q_FOREACH (FieldModel *f, tbl->fields()) {
2018-10-15 22:34:50 +08:00
model->setHeaderData(fieldIndex++,
Qt::Horizontal,
f->displayName);
}
2018-02-18 22:58:55 +08:00
}
2018-02-13 23:39:21 +08:00
}
2019-06-18 21:40:40 +08:00
template<class T>
Q_OUTOFLINE_TEMPLATE void Query<T>::toModel(SqlModel *model)
{
2020-08-10 14:42:06 +08:00
//Q_D(AbstractQuery);
2019-06-18 21:40:40 +08:00
2020-04-28 21:47:25 +08:00
d->sql = d->database->sqlGenerator()->selectCommand(
2019-06-18 21:40:40 +08:00
d->tableName,
d->fieldPhrase,
d->wherePhrase, d->orderPhrase, d->relations,
d->skip, d->take);
model->setTable(toList());
/*
DatabaseModel dbModel = d->database->model();
model->setQuery(d->sql, d->database->database());
int fieldIndex = 0;
if (d->fieldPhrase.data.count()) {
2021-03-14 16:42:04 +08:00
Q_FOREACH (const PhraseData *pd, d->fieldPhrase.data) {
2019-06-18 21:40:40 +08:00
QString displayName = dbModel.tableByClassName(pd->className)
->field(pd->fieldName)->displayName;
model->setHeaderData(fieldIndex++,
Qt::Horizontal,
displayName);
}
} else {
TableModel *tbl = d->database->model().tableByName(d->tableName);
2021-03-14 16:42:04 +08:00
Q_FOREACH (FieldModel *f, tbl->fields()) {
2019-06-18 21:40:40 +08:00
model->setHeaderData(fieldIndex++,
Qt::Horizontal,
f->displayName);
}
}*/
}
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
{
2020-08-10 14:42:06 +08:00
//Q_D(const AbstractQuery);
2017-07-25 22:10:43 +08:00
return d->sql;
}
2019-06-08 20:13:13 +08:00
//TODO: complete this class later
//class RawQuery : public Query<void>
//{
//public:
// void setRawCommand(const QString &sql) {
// }
//};
2017-02-01 18:01:21 +08:00
NUT_END_NAMESPACE
2016-05-12 14:08:58 +08:00
2020-08-08 15:29:16 +08:00
#endif // NUT_QUERY_H