Movable query (#107)

Query<T> and BulkInserter are now movable
This commit is contained in:
Hamed Masafi 2020-08-11 11:14:45 +04:30 committed by GitHub
parent b02435e17f
commit f7ef6d9878
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 290 additions and 357 deletions

View File

@ -1,43 +0,0 @@
/**************************************************************************
**
** 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/>.
**
**************************************************************************/
#include "abstractquery.h"
#include "abstractquery_p.h"
NUT_BEGIN_NAMESPACE
AbstractQuery::AbstractQuery(QObject *parent) : QObject(parent)
, d_ptr(new AbstractQueryPrivate(this))
{
}
Nut::AbstractQueryPrivate::AbstractQueryPrivate(Nut::AbstractQuery *parent) :
q_ptr(parent), skip(0), take(0)
{
}
Nut::AbstractQueryPrivate::~AbstractQueryPrivate()
{
}
NUT_END_NAMESPACE

View File

@ -1,53 +0,0 @@
/**************************************************************************
**
** 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 NUT_ABSTRACTQUERY_H
#define NUT_ABSTRACTQUERY_H
#include <QtCore/QObject>
#include <QtCore/qglobal.h>
#include <QtCore/QExplicitlySharedDataPointer>
#include "defines.h"
#include "abstractquery_p.h"
NUT_BEGIN_NAMESPACE
class AbstractQueryPrivate;
class NUT_EXPORT AbstractQuery : public QObject
{
Q_OBJECT
protected:
AbstractQueryPrivate *d_ptr;
Q_DECLARE_PRIVATE(AbstractQuery)
public:
explicit AbstractQuery(QObject *parent = nullptr);
protected:
// void addTableToSet(TableSetBase *set, Table *table);
public slots:
};
NUT_END_NAMESPACE
#endif // NUT_ABSTRACTQUERY_H

View File

@ -1,71 +0,0 @@
/**************************************************************************
**
** 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 NUT_QUERY_P_H
#define NUT_QUERY_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
// of qapplication_*.cpp, qwidget*.cpp and qfiledialog.cpp. This header
// file may change from version to version without notice, or even be removed.
//
// We mean it.
//
#include "phrase.h"
#include <QtCore/QList>
#include <QtCore/QString>
#include <QtCore/QSharedData>
NUT_BEGIN_NAMESPACE
class Database;
class AbstractTableSet;
class AbstractQuery;
struct RelationModel;
class NUT_EXPORT AbstractQueryPrivate {
AbstractQuery *q_ptr;
Q_DECLARE_PUBLIC(AbstractQuery)
public:
explicit AbstractQueryPrivate(AbstractQuery *parent);
~AbstractQueryPrivate();
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;
};
NUT_END_NAMESPACE
#endif // NUT_QUERY_P_H

View File

@ -1,4 +1,6 @@
#include "bulkinserter.h" #include "bulkinserter.h"
#include "bulkinserter_p.h"
#include "phrases/phraselist.h" #include "phrases/phraselist.h"
#include "database.h" #include "database.h"
#include "abstractsqlgenerator.h" #include "abstractsqlgenerator.h"
@ -6,23 +8,47 @@
#include <QtCore/QDebug> #include <QtCore/QDebug>
Nut::BulkInserter::BulkInserter(Nut::Database *db, QString &className) NUT_BEGIN_NAMESPACE
: _database(db), _fieldCount(0)
BulkInserterPrivate::BulkInserterPrivate(Database *db)
: database(db), fieldCount(0)
{ {
}
BulkInserter::BulkInserter(Database *db, QString &className)
: d_ptr(new BulkInserterPrivate(db))
{
Q_D(BulkInserter);
foreach (TableModel *m, db->model()) foreach (TableModel *m, db->model())
if (m->className() == className) if (m->className() == className)
_className = m->name(); d->className = m->name();
} }
void Nut::BulkInserter::setFields(const Nut::PhraseList &ph) BulkInserter::BulkInserter(const BulkInserter &other)
{ {
_fields = ph; d_ptr = other.d_ptr;
_fieldCount = static_cast<size_t>(ph.data.count());
} }
void Nut::BulkInserter::insert(std::initializer_list<QVariant> vars) BulkInserter::BulkInserter(BulkInserter &&other)
{ {
if (vars.size() != _fieldCount) { d_ptr = other.d_ptr;
other.d_ptr = nullptr;
}
void BulkInserter::setFields(const PhraseList &ph)
{
Q_D(BulkInserter);
d->fields = ph;
d->fieldCount = static_cast<size_t>(ph.data.count());
}
void BulkInserter::insert(std::initializer_list<QVariant> vars)
{
Q_D(BulkInserter);
if (vars.size() != d->fieldCount) {
qInfo("Number of rows mistake"); qInfo("Number of rows mistake");
return; return;
} }
@ -31,13 +57,17 @@ void Nut::BulkInserter::insert(std::initializer_list<QVariant> vars)
std::initializer_list<QVariant>::iterator it; std::initializer_list<QVariant>::iterator it;
for (it = vars.begin(); it != vars.end(); ++it) for (it = vars.begin(); it != vars.end(); ++it)
list.append(*it); list.append(*it);
variants.append(list); d->variants.append(list);
} }
int Nut::BulkInserter::apply() int BulkInserter::apply()
{ {
auto sql = _database->sqlGenerator()->insertBulk(_className, _fields, variants); Q_D(BulkInserter);
QSqlQuery q = _database->exec(sql); auto sql = d->database->sqlGenerator()->insertBulk(d->className,
d->fields,
d->variants);
QSqlQuery q = d->database->exec(sql);
return q.numRowsAffected(); return q.numRowsAffected();
} }
NUT_END_NAMESPACE

View File

@ -12,16 +12,16 @@ NUT_BEGIN_NAMESPACE
class PhraseList; class PhraseList;
class Database; class Database;
class BulkInserterPrivate;
class NUT_EXPORT BulkInserter class NUT_EXPORT BulkInserter
{ {
Database *_database; Q_DECLARE_PRIVATE(BulkInserter);
QString _className;
Nut::PhraseList _fields;
QList<QVariantList> variants;
size_t _fieldCount;
public: public:
BulkInserter(Database *db, QString &className); BulkInserter(Database *db, QString &className);
BulkInserter(const BulkInserter &other);
BulkInserter(BulkInserter &&other);
void setFields(const PhraseList &ph); void setFields(const PhraseList &ph);
void insert(std::initializer_list<QVariant> vars); void insert(std::initializer_list<QVariant> vars);
@ -30,6 +30,9 @@ public:
insert({args...}); insert({args...});
} }
int apply(); int apply();
private:
BulkInserterPrivate *d_ptr;
}; };
NUT_END_NAMESPACE NUT_END_NAMESPACE

23
src/nut/bulkinserter_p.h Normal file
View File

@ -0,0 +1,23 @@
#ifndef BULKINSERTER_P_H
#define BULKINSERTER_P_H
#include <QtNut/phraselist.h>
NUT_BEGIN_NAMESPACE
class Database;
class BulkInserterPrivate
{
public:
BulkInserterPrivate(Database *db);
Database *database;
QString className;
PhraseList fields;
QList<QVariantList> variants;
size_t fieldCount;
};
NUT_END_NAMESPACE
#endif // BULKINSERTER_P_H

View File

@ -281,10 +281,8 @@ bool DatabasePrivate::getCurrectSchema()
DatabaseModel DatabasePrivate::getLastSchema() DatabaseModel DatabasePrivate::getLastSchema()
{ {
Row<ChangeLogTable> u = changeLogs->query() Row<ChangeLogTable> u = changeLogs->query()
->orderBy(!ChangeLogTable::idField()) .orderBy(!ChangeLogTable::idField())
->first(); .first();
// DatabaseModel ret(q->metaObject()->className());
if (u) { if (u) {
QJsonParseError e; QJsonParseError e;

View File

@ -48,8 +48,7 @@ HEADERS += \
$$PWD/phrases/phraselist.h \ $$PWD/phrases/phraselist.h \
$$PWD/phrases/datephrase.h \ $$PWD/phrases/datephrase.h \
$$PWD/table_p.h \ $$PWD/table_p.h \
$$PWD/abstractquery.h \ bulkinserter_p.h
$$PWD/abstractquery_p.h
SOURCES += \ SOURCES += \
$$PWD/generators/abstractsqlgenerator.cpp \ $$PWD/generators/abstractsqlgenerator.cpp \
@ -78,8 +77,7 @@ SOURCES += \
$$PWD/phrases/phrasedata.cpp \ $$PWD/phrases/phrasedata.cpp \
$$PWD/phrases/phrasedatalist.cpp \ $$PWD/phrases/phrasedatalist.cpp \
$$PWD/phrases/phraselist.cpp \ $$PWD/phrases/phraselist.cpp \
$$PWD/phrases/datephrase.cpp \ $$PWD/phrases/datephrase.cpp
$$PWD/abstractquery.cpp
load(qt_module) load(qt_module)

View File

@ -36,8 +36,6 @@
#endif #endif
#include <QtNut/table.h> #include <QtNut/table.h>
#include <QtNut/abstractquery.h>
#include <QtNut/database.h> #include <QtNut/database.h>
#include <QtNut/databasemodel.h> #include <QtNut/databasemodel.h>
#include <QtNut/abstracttableset.h> #include <QtNut/abstracttableset.h>
@ -48,34 +46,78 @@
NUT_BEGIN_NAMESPACE NUT_BEGIN_NAMESPACE
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() {
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;
}
QueryData() : skip(0), take(0)
{ }
QueryData(Database *db) : database(db), skip(0), take(0)
{ }
};
template <class T> template <class T>
class Query : public AbstractQuery class Query
{ {
bool m_autoDelete; QueryData *d;
public: public:
explicit Query(Database *database, AbstractTableSet *tableSet, bool autoDelete); explicit Query(Database *database, AbstractTableSet *tableSet);
Query (const Query<T> &other);
Query (Query<T> &&other);
~Query(); ~Query();
Query<T>& operator=(const Query<T> &q);
//ddl //ddl
Query<T> *join(const QString &className); Query<T> &join(const QString &className);
Query<T> *join(Table *c); Query<T> &join(Table *c);
template<class TABLE> template<class TABLE>
Query<T> *join() Query<T> &join()
{ {
join(TABLE::staticMetaObject.className()); join(TABLE::staticMetaObject.className());
return this; return *this;
} }
// Query<T> *orderBy(QString fieldName, QString type); // Query<T> &orderBy(QString fieldName, QString type);
Query<T> *skip(int n); Query<T> &skip(int n);
Query<T> *take(int n); Query<T> &take(int n);
Query<T> *fields(const PhraseList &ph); Query<T> &fields(const PhraseList &ph);
Query<T> *orderBy(const PhraseList &ph); Query<T> &orderBy(const PhraseList &ph);
Query<T> *where(const ConditionalPhrase &ph); Query<T> &where(const ConditionalPhrase &ph);
Query<T> *setWhere(const ConditionalPhrase &ph); Query<T> &setWhere(const ConditionalPhrase &ph);
//data selecting //data selecting
Row<T> first(); Row<T> first();
@ -110,7 +152,7 @@ template<typename T>
template<typename O> template<typename O>
Q_OUTOFLINE_TEMPLATE QList<O> Query<T>::select(const std::function<O (const QSqlQuery &)> allocator) Q_OUTOFLINE_TEMPLATE QList<O> Query<T>::select(const std::function<O (const QSqlQuery &)> allocator)
{ {
Q_D(AbstractQuery); //Q_D(AbstractQuery);
QList<O> ret; QList<O> ret;
d->joins.prepend(d->tableName); d->joins.prepend(d->tableName);
@ -129,23 +171,20 @@ Q_OUTOFLINE_TEMPLATE QList<O> Query<T>::select(const std::function<O (const QSql
ret.append(obj); ret.append(obj);
} }
if (m_autoDelete)
deleteLater();
return ret; return ret;
} }
//template <typename T> //template <typename T>
//inline Query<T> *createQuery(TableSet<T> *tableSet) //inline Query<T> &createQuery(TableSet<T> *tableSet)
//{ //{
// return tableSet->query(); // return tableSet->query();
//} //}
template <class T> template <class T>
Q_OUTOFLINE_TEMPLATE Query<T>::Query(Database *database, AbstractTableSet *tableSet, Q_OUTOFLINE_TEMPLATE Query<T>::Query(Database *database, AbstractTableSet *tableSet)
bool autoDelete) : d(new QueryData(database))
: AbstractQuery(database), m_autoDelete(autoDelete)
{ {
Q_D(AbstractQuery); //Q_D(AbstractQuery);
d->database = database; d->database = database;
d->tableSet = tableSet; d->tableSet = tableSet;
@ -156,17 +195,40 @@ Q_OUTOFLINE_TEMPLATE Query<T>::Query(Database *database, AbstractTableSet *table
->name(); ->name();
} }
template<class T>
Q_OUTOFLINE_TEMPLATE Query<T>::Query(const Query<T> &other) {
d = other.d->clone();
}
template<class T>
Q_OUTOFLINE_TEMPLATE Query<T>::Query(Query<T> &&other) {
d = std::move(other.d);
other.d = nullptr;
}
template <class T> template <class T>
Q_OUTOFLINE_TEMPLATE Query<T>::~Query() Q_OUTOFLINE_TEMPLATE Query<T>::~Query()
{ {
Q_D(AbstractQuery); //Q_D(AbstractQuery);
delete d; delete d;
} }
template<class T>
Q_OUTOFLINE_TEMPLATE Query<T> &Query<T>::operator=(const Query<T> &q)
{
if (this != &q)
{
QueryData *p = q.d ? q.d->clone() : nullptr;
delete d;
d = p;
}
return *this;
}
template <class T> template <class T>
Q_OUTOFLINE_TEMPLATE RowList<T> Query<T>::toList(int count) Q_OUTOFLINE_TEMPLATE RowList<T> Query<T>::toList(int count)
{ {
Q_D(AbstractQuery); //Q_D(AbstractQuery);
RowList<T> returnList; RowList<T> returnList;
d->select = QStringLiteral("*"); d->select = QStringLiteral("*");
@ -323,7 +385,7 @@ Q_OUTOFLINE_TEMPLATE RowList<T> Query<T>::toList(int count)
} }
row->setStatus(Table::FetchedFromDB); row->setStatus(Table::FetchedFromDB);
row->setParent(this); // row->setParent(this);
row->clear(); row->clear();
//set last created row //set last created row
@ -331,10 +393,6 @@ Q_OUTOFLINE_TEMPLATE RowList<T> Query<T>::toList(int count)
} //while } //while
} // while } // while
#ifndef NUT_SHARED_POINTER
if (m_autoDelete)
deleteLater();
#endif
return returnList; return returnList;
} }
@ -343,7 +401,7 @@ template <typename T>
template <typename F> template <typename F>
Q_OUTOFLINE_TEMPLATE QList<F> Query<T>::select(const FieldPhrase<F> f) Q_OUTOFLINE_TEMPLATE QList<F> Query<T>::select(const FieldPhrase<F> f)
{ {
Q_D(AbstractQuery); //Q_D(AbstractQuery);
QList<F> ret; QList<F> ret;
d->joins.prepend(d->tableName); d->joins.prepend(d->tableName);
@ -361,8 +419,6 @@ Q_OUTOFLINE_TEMPLATE QList<F> Query<T>::select(const FieldPhrase<F> f)
ret.append(v.value<F>()); ret.append(v.value<F>());
} }
if (m_autoDelete)
deleteLater();
return ret; return ret;
} }
@ -381,7 +437,7 @@ Q_OUTOFLINE_TEMPLATE Row<T> Query<T>::first()
template <class T> template <class T>
Q_OUTOFLINE_TEMPLATE int Query<T>::count() Q_OUTOFLINE_TEMPLATE int Query<T>::count()
{ {
Q_D(AbstractQuery); //Q_D(AbstractQuery);
d->joins.prepend(d->tableName); d->joins.prepend(d->tableName);
d->select = QStringLiteral("COUNT(*)"); d->select = QStringLiteral("COUNT(*)");
@ -401,7 +457,7 @@ Q_OUTOFLINE_TEMPLATE int Query<T>::count()
template <class T> template <class T>
Q_OUTOFLINE_TEMPLATE QVariant Query<T>::max(const FieldPhrase<int> &f) Q_OUTOFLINE_TEMPLATE QVariant Query<T>::max(const FieldPhrase<int> &f)
{ {
Q_D(AbstractQuery); //Q_D(AbstractQuery);
d->joins.prepend(d->tableName); d->joins.prepend(d->tableName);
d->sql = d->database->sqlGenerator()->selectCommand( d->sql = d->database->sqlGenerator()->selectCommand(
@ -419,7 +475,7 @@ Q_OUTOFLINE_TEMPLATE QVariant Query<T>::max(const FieldPhrase<int> &f)
template <class T> template <class T>
Q_OUTOFLINE_TEMPLATE QVariant Query<T>::min(const FieldPhrase<int> &f) Q_OUTOFLINE_TEMPLATE QVariant Query<T>::min(const FieldPhrase<int> &f)
{ {
Q_D(AbstractQuery); //Q_D(AbstractQuery);
d->joins.prepend(d->tableName); d->joins.prepend(d->tableName);
d->sql = d->database->sqlGenerator()->selectCommand( d->sql = d->database->sqlGenerator()->selectCommand(
@ -437,7 +493,7 @@ Q_OUTOFLINE_TEMPLATE QVariant Query<T>::min(const FieldPhrase<int> &f)
template <class T> template <class T>
Q_OUTOFLINE_TEMPLATE QVariant Query<T>::sum(const FieldPhrase<int> &f) Q_OUTOFLINE_TEMPLATE QVariant Query<T>::sum(const FieldPhrase<int> &f)
{ {
Q_D(AbstractQuery); //Q_D(AbstractQuery);
d->joins.prepend(d->tableName); d->joins.prepend(d->tableName);
d->sql = d->database->sqlGenerator()->selectCommand( d->sql = d->database->sqlGenerator()->selectCommand(
@ -455,7 +511,7 @@ Q_OUTOFLINE_TEMPLATE QVariant Query<T>::sum(const FieldPhrase<int> &f)
template <class T> template <class T>
Q_OUTOFLINE_TEMPLATE QVariant Query<T>::average(const FieldPhrase<int> &f) Q_OUTOFLINE_TEMPLATE QVariant Query<T>::average(const FieldPhrase<int> &f)
{ {
Q_D(AbstractQuery); //Q_D(AbstractQuery);
d->joins.prepend(d->tableName); d->joins.prepend(d->tableName);
d->sql = d->database->sqlGenerator()->selectCommand( d->sql = d->database->sqlGenerator()->selectCommand(
@ -473,7 +529,7 @@ Q_OUTOFLINE_TEMPLATE QVariant Query<T>::average(const FieldPhrase<int> &f)
template<class T> template<class T>
Q_OUTOFLINE_TEMPLATE QVariant Query<T>::insert(const AssignmentPhraseList &p) Q_OUTOFLINE_TEMPLATE QVariant Query<T>::insert(const AssignmentPhraseList &p)
{ {
Q_D(AbstractQuery); //Q_D(AbstractQuery);
d->sql = d->database->sqlGenerator() d->sql = d->database->sqlGenerator()
->insertCommand(d->tableName, p); ->insertCommand(d->tableName, p);
QSqlQuery q = d->database->exec(d->sql); QSqlQuery q = d->database->exec(d->sql);
@ -482,9 +538,9 @@ Q_OUTOFLINE_TEMPLATE QVariant Query<T>::insert(const AssignmentPhraseList &p)
} }
template <class T> template <class T>
Q_OUTOFLINE_TEMPLATE Query<T> *Query<T>::join(const QString &className) Q_OUTOFLINE_TEMPLATE Query<T> &Query<T>::join(const QString &className)
{ {
Q_D(AbstractQuery); //Q_D(AbstractQuery);
RelationModel *rel = d->database->model() RelationModel *rel = d->database->model()
.relationByClassNames(d->className, className); .relationByClassNames(d->className, className);
@ -495,85 +551,85 @@ Q_OUTOFLINE_TEMPLATE Query<T> *Query<T>::join(const QString &className)
if (!rel) { if (!rel) {
qDebug() << "No relation between" << d->className qDebug() << "No relation between" << d->className
<< "and" << className; << "and" << className;
return this; return *this;
} }
d->relations.append(rel); d->relations.append(rel);
d->joins.append(className); d->joins.append(className);
return this; return *this;
} }
template<class T> template<class T>
Q_OUTOFLINE_TEMPLATE Query<T> *Query<T>::join(Table *c) Q_OUTOFLINE_TEMPLATE Query<T> &Query<T>::join(Table *c)
{ {
join(c->metaObject()->className()); join(c->metaObject()->className());
return this; return *this;
} }
template <class T> template <class T>
Q_OUTOFLINE_TEMPLATE Query<T> *Query<T>::where(const ConditionalPhrase &ph) Q_OUTOFLINE_TEMPLATE Query<T> &Query<T>::where(const ConditionalPhrase &ph)
{ {
Q_D(AbstractQuery); //Q_D(AbstractQuery);
if (d->wherePhrase.data) if (d->wherePhrase.data)
d->wherePhrase = d->wherePhrase && ph; d->wherePhrase = d->wherePhrase && ph;
else else
d->wherePhrase = ph; d->wherePhrase = ph;
return this; return *this;
} }
template <class T> template <class T>
Q_OUTOFLINE_TEMPLATE Query<T> *Query<T>::setWhere(const ConditionalPhrase &ph) Q_OUTOFLINE_TEMPLATE Query<T> &Query<T>::setWhere(const ConditionalPhrase &ph)
{ {
Q_D(AbstractQuery); //Q_D(AbstractQuery);
d->wherePhrase = ph; d->wherePhrase = ph;
return this; return *this;
} }
template<class T> template<class T>
Q_OUTOFLINE_TEMPLATE Query<T> *Query<T>::skip(int n) Q_OUTOFLINE_TEMPLATE Query<T> &Query<T>::skip(int n)
{ {
Q_D(AbstractQuery); //Q_D(AbstractQuery);
d->skip = n; d->skip = n;
return this; return *this;
} }
template<class T> template<class T>
Q_OUTOFLINE_TEMPLATE Query<T> *Query<T>::take(int n) Q_OUTOFLINE_TEMPLATE Query<T> &Query<T>::take(int n)
{ {
Q_D(AbstractQuery); //Q_D(AbstractQuery);
d->take = n; d->take = n;
return this; return *this;
} }
template<class T> template<class T>
Q_OUTOFLINE_TEMPLATE Query<T> *Query<T>::fields(const PhraseList &ph) Q_OUTOFLINE_TEMPLATE Query<T> &Query<T>::fields(const PhraseList &ph)
{ {
Q_D(AbstractQuery); //Q_D(AbstractQuery);
d->fieldPhrase = ph; d->fieldPhrase = ph;
return this; return *this;
} }
//template <class T> //template <class T>
//Q_OUTOFLINE_TEMPLATE Query<T> *Query<T>::orderBy(QString fieldName, //Q_OUTOFLINE_TEMPLATE Query<T> &Query<T>::orderBy(QString fieldName,
// QString type) // QString type)
//{ //{
// Q_D(AbstractQuery); // //Q_D(AbstractQuery);
// d->orderPhrases.append(fieldName, type); // d->orderPhrases.append(fieldName, type);
// return this; // return *this;
//} //}
template <class T> template <class T>
Q_OUTOFLINE_TEMPLATE Query<T> *Query<T>::orderBy(const PhraseList &ph) Q_OUTOFLINE_TEMPLATE Query<T> &Query<T>::orderBy(const PhraseList &ph)
{ {
Q_D(AbstractQuery); //Q_D(AbstractQuery);
d->orderPhrase = ph; d->orderPhrase = ph;
return this; return *this;
} }
template <class T> template <class T>
Q_OUTOFLINE_TEMPLATE int Query<T>::update(const AssignmentPhraseList &ph) Q_OUTOFLINE_TEMPLATE int Query<T>::update(const AssignmentPhraseList &ph)
{ {
Q_D(AbstractQuery); //Q_D(AbstractQuery);
d->sql = d->database->sqlGenerator()->updateCommand( d->sql = d->database->sqlGenerator()->updateCommand(
d->tableName, d->tableName,
@ -582,22 +638,18 @@ Q_OUTOFLINE_TEMPLATE int Query<T>::update(const AssignmentPhraseList &ph)
QSqlQuery q = d->database->exec(d->sql); QSqlQuery q = d->database->exec(d->sql);
if (m_autoDelete)
deleteLater();
return q.numRowsAffected(); return q.numRowsAffected();
} }
template <class T> template <class T>
Q_OUTOFLINE_TEMPLATE int Query<T>::remove() Q_OUTOFLINE_TEMPLATE int Query<T>::remove()
{ {
Q_D(AbstractQuery); //Q_D(AbstractQuery);
d->sql = d->database->sqlGenerator()->deleteCommand( d->sql = d->database->sqlGenerator()->deleteCommand(
d->tableName, d->wherePhrase); d->tableName, d->wherePhrase);
QSqlQuery q = d->database->exec(d->sql); QSqlQuery q = d->database->exec(d->sql);
if (m_autoDelete)
deleteLater();
return q.numRowsAffected(); return q.numRowsAffected();
} }
@ -612,7 +664,7 @@ Q_OUTOFLINE_TEMPLATE QSqlQueryModel *Query<T>::toModel()
template <class T> template <class T>
Q_OUTOFLINE_TEMPLATE void Query<T>::toModel(QSqlQueryModel *model) Q_OUTOFLINE_TEMPLATE void Query<T>::toModel(QSqlQueryModel *model)
{ {
Q_D(AbstractQuery); //Q_D(AbstractQuery);
d->sql = d->database->sqlGenerator()->selectCommand( d->sql = d->database->sqlGenerator()->selectCommand(
d->tableName, d->tableName,
@ -649,7 +701,7 @@ Q_OUTOFLINE_TEMPLATE void Query<T>::toModel(QSqlQueryModel *model)
template<class T> template<class T>
Q_OUTOFLINE_TEMPLATE void Query<T>::toModel(SqlModel *model) Q_OUTOFLINE_TEMPLATE void Query<T>::toModel(SqlModel *model)
{ {
Q_D(AbstractQuery); //Q_D(AbstractQuery);
d->sql = d->database->sqlGenerator()->selectCommand( d->sql = d->database->sqlGenerator()->selectCommand(
d->tableName, d->tableName,
@ -686,7 +738,7 @@ Q_OUTOFLINE_TEMPLATE void Query<T>::toModel(SqlModel *model)
template <class T> template <class T>
Q_OUTOFLINE_TEMPLATE QString Query<T>::sqlCommand() const Q_OUTOFLINE_TEMPLATE QString Query<T>::sqlCommand() const
{ {
Q_D(const AbstractQuery); //Q_D(const AbstractQuery);
return d->sql; return d->sql;
} }

View File

@ -63,8 +63,8 @@ public:
Row<T> at(int i) const; Row<T> at(int i) const;
Row<T> operator[](int i) const; Row<T> operator[](int i) const;
Query<T> *query(bool autoDelete = true); Query<T> query();
BulkInserter *bulkInserter(); BulkInserter bulkInserter();
}; };
template<class T> template<class T>
@ -80,18 +80,15 @@ Q_OUTOFLINE_TEMPLATE TableSet<T>::TableSet(Table *parent) : AbstractTableSet(par
} }
template<class T> template<class T>
Q_OUTOFLINE_TEMPLATE Query<T> *TableSet<T>::query(bool autoDelete) Q_OUTOFLINE_TEMPLATE Query<T> TableSet<T>::query()
{ {
Query<T> *q = new Query<T>(data->database, this, autoDelete); return Query<T>(data->database, this);
return q;
} }
template<class T> template<class T>
Q_OUTOFLINE_TEMPLATE BulkInserter *TableSet<T>::bulkInserter() Q_OUTOFLINE_TEMPLATE BulkInserter TableSet<T>::bulkInserter()
{ {
BulkInserter *bi = new BulkInserter(data->database, data->childClassName); return BulkInserter(data->database, data->childClassName);
return bi;
} }
template<class T> template<class T>

View File

@ -38,10 +38,10 @@ void BasicTest::initTestCase()
bool ok = db.open(); bool ok = db.open();
QVERIFY(ok); QVERIFY(ok);
db.comments()->query()->remove(); db.comments()->query().remove();
db.posts()->query()->remove(); db.posts()->query().remove();
db.users()->query()->remove(); db.users()->query().remove();
db.scores()->query()->remove(); db.scores()->query().remove();
} }
void BasicTest::dataSchema() void BasicTest::dataSchema()
@ -97,7 +97,7 @@ void BasicTest::createPost()
void BasicTest::createPost2() void BasicTest::createPost2()
{ {
//create post on the fly //create post on the fly
QVariant postIdVar = db.posts()->query()->insert( QVariant postIdVar = db.posts()->query().insert(
(Post::titleField() = QStringLiteral("This is a sample")) (Post::titleField() = QStringLiteral("This is a sample"))
& (Post::isPublicField() = true)); & (Post::isPublicField() = true));
@ -123,15 +123,15 @@ void BasicTest::createPost2()
void BasicTest::updatePostOnTheFly() void BasicTest::updatePostOnTheFly()
{ {
auto c = db.posts()->query() auto c = db.posts()->query()
->where(Post::idField() == postId) .where(Post::idField() == postId)
->update(Post::titleField() = QStringLiteral("New title")); .update(Post::titleField() = QStringLiteral("New title"));
QCOMPARE(c, 1); QCOMPARE(c, 1);
auto titles = db.posts() auto titles = db.posts()
->query() ->query()
->where(Post::idField() == postId) .where(Post::idField() == postId)
->select(Post::titleField()); .select(Post::titleField());
QCOMPARE(titles.count(), 1); QCOMPARE(titles.count(), 1);
QCOMPARE(titles.at(0), QStringLiteral("New title")); QCOMPARE(titles.at(0), QStringLiteral("New title"));
@ -140,12 +140,12 @@ void BasicTest::updatePostOnTheFly()
void BasicTest::selectPublicts() void BasicTest::selectPublicts()
{ {
auto q = db.posts()->query() auto q = db.posts()->query()
->where(Post::isPublicField()) .where(Post::isPublicField())
->count(); .count();
auto q2 = db.posts()->query() auto q2 = db.posts()->query()
->where(!Post::isPublicField()) .where(!Post::isPublicField())
->count(); .count();
QCOMPARE(q, 1); QCOMPARE(q, 1);
QCOMPARE(q2, 1); QCOMPARE(q2, 1);
@ -154,11 +154,11 @@ void BasicTest::selectPublicts()
void BasicTest::selectPosts() void BasicTest::selectPosts()
{ {
auto q = db.posts()->query() auto q = db.posts()->query()
->join<Comment>() .join<Comment>()
->orderBy((!Post::saveDateField()) | Post::bodyField()) .orderBy((!Post::saveDateField()) | Post::bodyField())
->setWhere(Post::idField() == postId); .where(Post::idField() == postId);
auto posts = q->toList(); auto posts = q.toList();
post = posts.at(0); post = posts.at(0);
post->setBody(QStringLiteral("")); post->setBody(QStringLiteral(""));
@ -179,9 +179,9 @@ void BasicTest::selectScoreAverage()
bool ok; bool ok;
auto avg = db.scores() auto avg = db.scores()
->query() ->query()
->join<Post>() .join<Post>()
->where(Post::idField() == postId) .where(Post::idField() == postId)
->average(Score::scoreField()) .average(Score::scoreField())
.toInt(&ok); .toInt(&ok);
QVERIFY(ok); QVERIFY(ok);
@ -190,21 +190,21 @@ void BasicTest::selectScoreAverage()
void BasicTest::selectScoreSum() void BasicTest::selectScoreSum()
{ {
auto sum = db.scores()->query()->sum(Score::scoreField()); auto sum = db.scores()->query().sum(Score::scoreField());
QCOMPARE(sum, 20); QCOMPARE(sum, 20);
} }
void BasicTest::selectScoreCount() void BasicTest::selectScoreCount()
{ {
auto count = db.scores()->query()->count(); auto count = db.scores()->query().count();
QCOMPARE(count, 10); QCOMPARE(count, 10);
} }
void BasicTest::selectFirst() void BasicTest::selectFirst()
{ {
auto posts = db.posts()->query() auto posts = db.posts()->query()
->orderBy(Post::idField()) .orderBy(Post::idField())
->first(); .first();
QVERIFY(posts != Q_NULLPTR); QVERIFY(posts != Q_NULLPTR);
} }
@ -212,15 +212,15 @@ void BasicTest::selectFirst()
void BasicTest::selectPostsWithoutTitle() void BasicTest::selectPostsWithoutTitle()
{ {
auto q = db.posts()->query(); auto q = db.posts()->query();
q->setWhere(Post::titleField().isNull()); q.where(Post::titleField().isNull());
auto count = q->count(); auto count = q.count();
QCOMPARE(count, 0); QCOMPARE(count, 0);
} }
void BasicTest::selectPostIds() void BasicTest::selectPostIds()
{ {
auto q = db.posts()->query(); auto q = db.posts()->query();
auto ids = q->select(Post::idField()); auto ids = q.select(Post::idField());
QCOMPARE(ids.count(), 2); QCOMPARE(ids.count(), 2);
} }
@ -240,18 +240,17 @@ void BasicTest::testDate()
db.saveChanges(true); db.saveChanges(true);
auto q = db.posts()->query() auto q = db.posts()->query()
->setWhere(Post::idField() == newPost->id()) .where(Post::idField() == newPost->id())
->orderBy(Post::idField()) .orderBy(Post::idField())
->first(); .first();
QCOMPARE(q->saveDate(), d); QCOMPARE(q->saveDate(), d);
} }
void BasicTest::testLimitedQuery() void BasicTest::testLimitedQuery()
{ {
auto q = db.comments()->query(); auto comments = db.comments()->query()
auto comments = q->toList(2); .toList(2);
qDebug() << q->sqlCommand();
QCOMPARE(comments.length(), 2); QCOMPARE(comments.length(), 2);
} }
@ -274,17 +273,17 @@ void BasicTest::join()
void BasicTest::selectWithInvalidRelation() void BasicTest::selectWithInvalidRelation()
{ {
auto q = db.posts()->query(); auto q = db.posts()->query();
q->join(QStringLiteral("Invalid_Class_Name")); q.join(QStringLiteral("Invalid_Class_Name"));
q->toList(); q.toList();
} }
void BasicTest::modifyPost() void BasicTest::modifyPost()
{ {
auto q = db.posts()->query() auto q = db.posts()->query()
->setWhere(Post::idField() == postId) .where(Post::idField() == postId)
->orderBy(Post::idField()); .orderBy(Post::idField());
Nut::Row<Post> post = q->first(); Nut::Row<Post> post = q.first();
QTEST_ASSERT(post != nullptr); QTEST_ASSERT(post != nullptr);
@ -292,18 +291,18 @@ void BasicTest::modifyPost()
db.saveChanges(); db.saveChanges();
q = db.posts()->query() q = db.posts()->query()
->setWhere(Post::idField() == postId) .where(Post::idField() == postId)
->orderBy(Post::idField()); .orderBy(Post::idField());
post = q->first(); post = q.first();
PRINT(post->title()); PRINT(post->title());
QCOMPARE(post->title(), "new name"); QCOMPARE(post->title(), "new name");
} }
void BasicTest::emptyDatabase() void BasicTest::emptyDatabase()
{ {
// auto commentsCount = db.comments()->query()->remove(); // auto commentsCount = db.comments()->query().remove();
// auto postsCount = db.posts()->query()->remove(); // auto postsCount = db.posts()->query().remove();
// QTEST_ASSERT(postsCount == 3); // QTEST_ASSERT(postsCount == 3);
// QTEST_ASSERT(commentsCount == 6); // QTEST_ASSERT(commentsCount == 6);
} }

View File

@ -80,7 +80,7 @@ void DataTypesTest::initTestCase()
QTEST_ASSERT(ok); QTEST_ASSERT(ok);
db.sampleTables()->query()->remove(); db.sampleTables()->query().remove();
} }
void DataTypesTest::insert() void DataTypesTest::insert()
@ -130,7 +130,7 @@ void DataTypesTest::insert()
void DataTypesTest::retrive() void DataTypesTest::retrive()
{ {
Nut::RowList<SampleTable> list = db.sampleTables()->query()->toList(); Nut::RowList<SampleTable> list = db.sampleTables()->query().toList();
QTEST_ASSERT(list.count() == 1); QTEST_ASSERT(list.count() == 1);
Nut::Row<SampleTable> t = list.first(); Nut::Row<SampleTable> t = list.first();
@ -179,8 +179,8 @@ void DataTypesTest::retrive()
#define CHECK(name) \ #define CHECK(name) \
c = db.sampleTables()->query() \ c = db.sampleTables()->query() \
->where(SampleTable::f_ ## name ## Field() == f_ ## name) \ .where(SampleTable::f_ ## name ## Field() == f_ ## name) \
->count(); \ .count(); \
QTEST_ASSERT(c == 1); QTEST_ASSERT(c == 1);
void DataTypesTest::check() void DataTypesTest::check()
@ -224,7 +224,7 @@ void DataTypesTest::check()
void DataTypesTest::cleanupTestCase() void DataTypesTest::cleanupTestCase()
{ {
db.sampleTables()->query()->remove(); db.sampleTables()->query().remove();
db.close(); db.close();
PRINT_FORM(db); PRINT_FORM(db);

View File

@ -32,7 +32,7 @@ void DateTimeTest::initTestCase()
QTEST_ASSERT(db.open()); QTEST_ASSERT(db.open());
db.sampleTables()->query()->remove(); db.sampleTables()->query().remove();
} }
#define TEST_DATE(date, command, n) \ #define TEST_DATE(date, command, n) \
@ -42,8 +42,8 @@ do { \
db.sampleTables()->append(s); \ db.sampleTables()->append(s); \
db.saveChanges(); \ db.saveChanges(); \
auto count = db.sampleTables()->query() \ auto count = db.sampleTables()->query() \
->where(SampleTable::dField().command(n) == date.command(n)) \ .where(SampleTable::dField().command(n) == date.command(n)) \
->count(); \ .count(); \
QTEST_ASSERT(count); \ QTEST_ASSERT(count); \
} while (false) } while (false)
@ -54,8 +54,8 @@ do { \
db.sampleTables()->append(s); \ db.sampleTables()->append(s); \
db.saveChanges(); \ db.saveChanges(); \
auto count = db.sampleTables()->query() \ auto count = db.sampleTables()->query() \
->where(SampleTable::tField().command(n) == time.addSecs(num)) \ .where(SampleTable::tField().command(n) == time.addSecs(num)) \
->count(); \ .count(); \
QTEST_ASSERT(count); \ QTEST_ASSERT(count); \
} while (false) } while (false)
@ -66,8 +66,8 @@ do { \
db.sampleTables()->append(s); \ db.sampleTables()->append(s); \
db.saveChanges(); \ db.saveChanges(); \
auto count = db.sampleTables()->query() \ auto count = db.sampleTables()->query() \
->where(SampleTable::dtField().command(n) == datetime.command(n)) \ .where(SampleTable::dtField().command(n) == datetime.command(n)) \
->count(); \ .count(); \
QTEST_ASSERT(count); \ QTEST_ASSERT(count); \
} while (false) } while (false)
@ -78,8 +78,8 @@ do { \
db.sampleTables()->append(s); \ db.sampleTables()->append(s); \
db.saveChanges(); \ db.saveChanges(); \
auto count = db.sampleTables()->query() \ auto count = db.sampleTables()->query() \
->where(SampleTable::dtField().command(n) == datetime.addSecs(num)) \ .where(SampleTable::dtField().command(n) == datetime.addSecs(num)) \
->count(); \ .count(); \
QTEST_ASSERT(count); \ QTEST_ASSERT(count); \
} while (false) } while (false)
@ -136,7 +136,7 @@ void DateTimeTest::dateTimeAdd()
void DateTimeTest::datePart() void DateTimeTest::datePart()
{ {
db.sampleTables()->query()->remove(); db.sampleTables()->query().remove();
QDate d = QDate::currentDate(); QDate d = QDate::currentDate();
auto s = Nut::create<SampleTable>(); auto s = Nut::create<SampleTable>();
@ -146,18 +146,18 @@ void DateTimeTest::datePart()
int count; int count;
count = db.sampleTables()->query()->where(SampleTable::dField().year() == d.year())->count(); count = db.sampleTables()->query().where(SampleTable::dField().year() == d.year()).count();
QTEST_ASSERT(count); QTEST_ASSERT(count);
count = db.sampleTables()->query()->where(SampleTable::dField().month() == d.month())->count(); count = db.sampleTables()->query().where(SampleTable::dField().month() == d.month()).count();
QTEST_ASSERT(count); QTEST_ASSERT(count);
count = db.sampleTables()->query()->where(SampleTable::dField().day() == d.day())->count(); count = db.sampleTables()->query().where(SampleTable::dField().day() == d.day()).count();
QTEST_ASSERT(count); QTEST_ASSERT(count);
} }
void DateTimeTest::timePart() void DateTimeTest::timePart()
{ {
db.sampleTables()->query()->remove(); db.sampleTables()->query().remove();
QTime t = QTime::currentTime(); QTime t = QTime::currentTime();
auto s = Nut::create<SampleTable>(); auto s = Nut::create<SampleTable>();
@ -167,17 +167,17 @@ void DateTimeTest::timePart()
int count; int count;
count = db.sampleTables()->query()->where(SampleTable::tField().hour() == t.hour())->count(); count = db.sampleTables()->query().where(SampleTable::tField().hour() == t.hour()).count();
QTEST_ASSERT(count); QTEST_ASSERT(count);
count = db.sampleTables()->query()->where(SampleTable::tField().minute() == t.minute())->count(); count = db.sampleTables()->query().where(SampleTable::tField().minute() == t.minute()).count();
QTEST_ASSERT(count); QTEST_ASSERT(count);
count = db.sampleTables()->query()->where(SampleTable::tField().second() == t.second())->count(); count = db.sampleTables()->query().where(SampleTable::tField().second() == t.second()).count();
QTEST_ASSERT(count); QTEST_ASSERT(count);
} }
void DateTimeTest::dateTimePart() void DateTimeTest::dateTimePart()
{ {
db.sampleTables()->query()->remove(); db.sampleTables()->query().remove();
QDateTime dt = QDateTime::currentDateTime(); QDateTime dt = QDateTime::currentDateTime();
auto s = Nut::create<SampleTable>(); auto s = Nut::create<SampleTable>();
@ -187,24 +187,24 @@ void DateTimeTest::dateTimePart()
int count; int count;
count = db.sampleTables()->query()->where(SampleTable::dtField().year() == dt.date().year())->count(); count = db.sampleTables()->query().where(SampleTable::dtField().year() == dt.date().year()).count();
QTEST_ASSERT(count); QTEST_ASSERT(count);
count = db.sampleTables()->query()->where(SampleTable::dtField().month() == dt.date().month())->count(); count = db.sampleTables()->query().where(SampleTable::dtField().month() == dt.date().month()).count();
QTEST_ASSERT(count); QTEST_ASSERT(count);
count = db.sampleTables()->query()->where(SampleTable::dtField().day() == dt.date().day())->count(); count = db.sampleTables()->query().where(SampleTable::dtField().day() == dt.date().day()).count();
QTEST_ASSERT(count); QTEST_ASSERT(count);
count = db.sampleTables()->query()->where(SampleTable::dtField().hour() == dt.time().hour())->count(); count = db.sampleTables()->query().where(SampleTable::dtField().hour() == dt.time().hour()).count();
QTEST_ASSERT(count); QTEST_ASSERT(count);
count = db.sampleTables()->query()->where(SampleTable::dtField().minute() == dt.time().minute())->count(); count = db.sampleTables()->query().where(SampleTable::dtField().minute() == dt.time().minute()).count();
QTEST_ASSERT(count); QTEST_ASSERT(count);
count = db.sampleTables()->query()->where(SampleTable::dtField().second() == dt.time().second())->count(); count = db.sampleTables()->query().where(SampleTable::dtField().second() == dt.time().second()).count();
QTEST_ASSERT(count); QTEST_ASSERT(count);
} }
void DateTimeTest::cleanupTestCase() void DateTimeTest::cleanupTestCase()
{ {
db.sampleTables()->query()->remove(); db.sampleTables()->query().remove();
db.close(); db.close();
} }

View File

@ -49,9 +49,9 @@ void TestJson::store()
int id = t->id(); int id = t->id();
auto newObj = db.sampleTable()->query() auto newObj = db.sampleTable()->query()
->where(Table::idField() == id) .where(Table::idField() == id)
->orderBy(Table::idField()) .orderBy(Table::idField())
->first(); .first();
Q_ASSERT(newObj != nullptr); Q_ASSERT(newObj != nullptr);
Q_ASSERT(newObj->doc() == t->doc()); Q_ASSERT(newObj->doc() == t->doc());

View File

@ -32,7 +32,7 @@ void UuidTest::initTestCase()
bool ok = db.open(); bool ok = db.open();
db.tests()->query()->remove(); db.tests()->query().remove();
uuid = QUuid::createUuid(); uuid = QUuid::createUuid();
QTEST_ASSERT(ok); QTEST_ASSERT(ok);
@ -54,7 +54,7 @@ void UuidTest::save()
void UuidTest::restore() void UuidTest::restore()
{ {
TIC(); TIC();
auto test = db.tests()->query()->first(); auto test = db.tests()->query().first();
TOC(); TOC();
QTEST_ASSERT(!test->id().isNull()); QTEST_ASSERT(!test->id().isNull());
QTEST_ASSERT(test->uuid() == uuid); QTEST_ASSERT(test->uuid() == uuid);

View File

@ -49,7 +49,7 @@ void Upgrades::version1()
DB1 db; DB1 db;
initDb(db); initDb(db);
QTEST_ASSERT(db.open()); QTEST_ASSERT(db.open());
db.sampleTable()->query()->remove(); db.sampleTable()->query().remove();
} }
void Upgrades::version2() void Upgrades::version2()
@ -72,7 +72,7 @@ void Upgrades::version3()
QTEST_ASSERT(db.open()); QTEST_ASSERT(db.open());
auto t = db.sampleTable()->query() auto t = db.sampleTable()->query()
->first(); .first();
QTEST_ASSERT(id == t->id()); QTEST_ASSERT(id == t->id());
} }