Merge pull request #1 from HamedMasafi/master

update
This commit is contained in:
bodhi369 2019-01-16 14:31:55 +08:00 committed by GitHub
commit e71a7ac2ed
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
38 changed files with 573 additions and 235 deletions

View File

@ -61,4 +61,10 @@ if(post) {
} }
``` ```
### Donate
Butcoin address: 1Dn1WHKkaxanXe4cTGDk4cFRRABxLUpEVj
![Wallet addresst](btc-qr.png)
For more information read [Wiki](wiki). For more information read [Wiki](wiki).

BIN
btc-qr.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 403 B

58
nut.qbs
View File

@ -1,12 +1,45 @@
import qbs import qbs
Product { Project {
type: "staticlibrary" // StaticLibrary {
// name: "nut_static"
// files: [
// "src/*.h",
// "src/*.cpp",
// "src/generators/*.h",
// "src/generators/*.cpp"
// ]
// Depends { name: 'cpp' }
// Depends { name: "Qt.core" }
// Depends { name: "Qt.sql" }
// Group { qbs.install: true; fileTagsFilter: product.type;}
// Export {
// Depends { name: "cpp" }
// Depends { name: "Qt.core" }
// Depends { name: "Qt.sql" }
// cpp.includePaths: [
// product.sourceDirectory + "/src",
// product.sourceDirectory + "/include"
// ]
// }
// }
DynamicLibrary {
name: "nut" name: "nut"
files: [
"src/*.h",
"src/*.cpp",
"src/generators/*.h",
"src/generators/*.cpp"
]
Depends { name: 'cpp' } Depends { name: 'cpp' }
Depends { name: "Qt.core" } Depends { name: "Qt.core" }
Depends { name: "Qt.sql" } Depends { name: "Qt.sql" }
Group { qbs.install: true; fileTagsFilter: product.type;}
Export { Export {
Depends { name: "cpp" } Depends { name: "cpp" }
Depends { name: "Qt.core" } Depends { name: "Qt.core" }
@ -16,24 +49,5 @@ Product {
product.sourceDirectory + "/include" product.sourceDirectory + "/include"
] ]
} }
}
files: [
"src/tableset.cpp",
"src/query.cpp",
"src/databasemodel.cpp",
"src/tablesetbase.cpp",
"src/changelogtable.cpp",
"src/querybase.cpp",
"src/tablemodel.cpp",
"src/wherephrase.cpp",
"src/table.cpp",
"src/database.cpp",
"src/generators/sqlgeneratorbase.cpp",
"src/generators/postgresqlgenerator.cpp",
"src/generators/mysqlgenerator.cpp",
"src/generators/sqlitegenerator.cpp",
"src/generators/sqlservergenerator.cpp",
"src/types/dbgeography.cpp",
"src/serializableobject.cpp"
]
} }

View File

@ -203,14 +203,25 @@ bool DatabasePrivate::getCurrectScheema()
QString name; QString name;
QString value; QString value;
if (!checkClassInfo(q->metaObject()->classInfo(i), if (!nutClassInfoString(q->metaObject()->classInfo(i),
type, name, value)) { type, name, value)) {
qDebug() << "No valid table in" << q->metaObject()->classInfo(i).value();
continue; continue;
} }
if (type == __nut_TABLE) {
if (type == __nut_TABLE) //name: table class name
//value: table variable name (table name in db)
tables.insert(name, value); tables.insert(name, value);
int typeId = QMetaType::type(name.toLocal8Bit() + "*");
if (!typeId)
qFatal("The class %s is not registered with qt meta object", qPrintable(name));
TableModel *sch = new TableModel(typeId, value);
currentModel.append(sch);
}
if (type == __nut_DB_VERSION) if (type == __nut_DB_VERSION)
currentModel.setVersion(name); currentModel.setVersion(name);
@ -249,21 +260,21 @@ bool DatabasePrivate::getCurrectScheema()
return true; return true;
} }
bool DatabasePrivate::checkClassInfo(const QMetaClassInfo &classInfo, QString &type, QString &name, QString &value) //bool DatabasePrivate::checkClassInfo(const QMetaClassInfo &classInfo, QString &type, QString &name, QString &value)
{ //{
if (!QString(classInfo.name()).startsWith(__nut_NAME_PERFIX)) { // if (!QString(classInfo.name()).startsWith(__nut_NAME_PERFIX)) {
return false; // return false;
} else { // } else {
QStringList parts = QString(classInfo.value()).split("\n"); // QStringList parts = QString(classInfo.value()).split("\n");
if (parts.count() != 3) // if (parts.count() != 3)
return false; // return false;
type = parts[0]; // type = parts[0];
name = parts[1]; // name = parts[1];
value = parts[2]; // value = parts[2];
return true; // return true;
} // }
} //}
DatabaseModel DatabasePrivate::getLastScheema() DatabaseModel DatabasePrivate::getLastScheema()
{ {

View File

@ -45,8 +45,8 @@ public:
DatabaseModel getLastScheema(); DatabaseModel getLastScheema();
bool getCurrectScheema(); bool getCurrectScheema();
bool checkClassInfo(const QMetaClassInfo &classInfo, // bool checkClassInfo(const QMetaClassInfo &classInfo,
QString &type, QString &name, QString &value); // QString &type, QString &name, QString &value);
QSqlDatabase db; QSqlDatabase db;
QString hostName; QString hostName;

View File

@ -233,7 +233,7 @@ void DatabaseModel::deleteAllModels()
while (i.hasNext()) { while (i.hasNext()) {
i.next(); i.next();
// cout << i.key() << ": " << i.value() << endl; // cout << i.key() << ": " << i.value() << endl;
delete i.value(); // qDeleteAll(i.value());
} }
// qDeleteAll(_models.values()); // qDeleteAll(_models.values());
_models.clear(); _models.clear();

View File

@ -26,6 +26,11 @@
#include "defines_p.h" #include "defines_p.h"
#include "qglobal.h" #include "qglobal.h"
#include <QString>
#include <QStringList>
#include <QVariant>
#include <QMetaClassInfo>
#ifdef NUT_COMPILE_STATIC #ifdef NUT_COMPILE_STATIC
# define NUT_EXPORT # define NUT_EXPORT
#else #else
@ -36,21 +41,96 @@
Q_CLASSINFO(__nut_NAME_PERFIX type #name #value, \ Q_CLASSINFO(__nut_NAME_PERFIX type #name #value, \
type "\n" #name "\n" #value) type "\n" #name "\n" #value)
#define NUT_INFO_STRING(type, name, value) \
Q_CLASSINFO(__nut_NAME_PERFIX type #name #value, \
type "\n" #name "\n" value)
inline bool nutClassInfo(const QMetaClassInfo &classInfo,
QString &type, QString &name, QVariant &value)
{
if (!QString(classInfo.name()).startsWith(__nut_NAME_PERFIX)) {
return false;
} else {
QStringList parts = QString(classInfo.value()).split("\n");
if (parts.count() != 3)
return false;
type = parts[0];
name = parts[1];
value = qVariantFromValue(parts[2]);
return true;
}
}
inline bool nutClassInfoString(const QMetaClassInfo &classInfo,
QString &type, QString &name, QString &value)
{
if (!QString(classInfo.name()).startsWith(__nut_NAME_PERFIX)) {
return false;
} else {
QStringList parts = QString(classInfo.value()).split("\n");
if (parts.count() != 3)
return false;
type = parts[0];
name = parts[1];
value = parts[2];
return true;
}
}
inline bool nutClassInfoBool(const QMetaClassInfo &classInfo,
QString &type, QString &name, bool &value)
{
if (!QString(classInfo.name()).startsWith(__nut_NAME_PERFIX)) {
return false;
} else {
QStringList parts = QString(classInfo.value()).split("\n");
if (parts.count() != 3)
return false;
QString buffer = parts[2].toLower();
if (buffer != "true" && buffer != "false")
return false;
type = parts[0];
name = parts[1];
value = (buffer == "true");
return true;
}
}
inline bool nutClassInfoInt(const QMetaClassInfo &classInfo,
QString &type, QString &name, bool &value)
{
if (!QString(classInfo.name()).startsWith(__nut_NAME_PERFIX)) {
return false;
} else {
QStringList parts = QString(classInfo.value()).split("\n");
if (parts.count() != 3)
return false;
bool ok;
type = parts[0];
name = parts[1];
value = parts[2].toInt(&ok);
return ok;
}
}
// Database // Database
#define NUT_DB_VERSION(version) \ #define NUT_DB_VERSION(version) \
NUT_INFO(__nut_DB_VERSION, version, 0) NUT_INFO(__nut_DB_VERSION, version, 0)
#define NUT_DECLARE_TABLE(type, name) \ #define NUT_DECLARE_TABLE(type, name) \
NUT_INFO(__nut_TABLE, type, name) \ NUT_INFO(__nut_TABLE, type, name) \
Q_PROPERTY(type* name READ name) \ Q_PROPERTY(NUT_WRAP_NAMESPACE(TableSet<type>) name READ name) \
Q_PROPERTY(NUT_WRAP_NAMESPACE(TableSet<type>) name##Table READ name##Table)\ NUT_WRAP_NAMESPACE(TableSet<type>) *m_##name; \
type* m_##name; \ public: \
NUT_WRAP_NAMESPACE(TableSet<type>) *m_##name##Table; \ static const type *_##name; \
public: \ NUT_WRAP_NAMESPACE(TableSet<type>) *name() const \
static const type _##name; \ { return m_##name; } \
type* name() const{ return m_##name; } \ private:
NUT_WRAP_NAMESPACE(TableSet<type>) *name##Table() const \
{ return m_##name##Table; }
//Table //Table
#define NUT_DECLARE_FIELD(type, name, read, write) \ #define NUT_DECLARE_FIELD(type, name, read, write) \
@ -58,7 +138,7 @@ public: \
NUT_INFO(__nut_FIELD, name, 0) \ NUT_INFO(__nut_FIELD, name, 0) \
type m_##name; \ type m_##name; \
public: \ public: \
static NUT_WRAP_NAMESPACE(FieldPhrase<type>) name ## Field(){ \ static NUT_WRAP_NAMESPACE(FieldPhrase<type>)& name ## Field(){ \
static NUT_WRAP_NAMESPACE(FieldPhrase<type>) f = \ static NUT_WRAP_NAMESPACE(FieldPhrase<type>) f = \
NUT_WRAP_NAMESPACE(FieldPhrase<type>) \ NUT_WRAP_NAMESPACE(FieldPhrase<type>) \
(staticMetaObject.className(), #name); \ (staticMetaObject.className(), #name); \
@ -99,11 +179,9 @@ public: \
return m_##n; \ return m_##n; \
} }
#define NUT_PRIMARY_KEY(x) NUT_INFO(__nut_PRIMARY_KEY, x, 0) #define NUT_PRIMARY_KEY(x) NUT_INFO(__nut_PRIMARY_KEY, x, 0)
#define NUT_AUTO_INCREMENT(x) NUT_INFO(__nut_AUTO_INCREMENT, x, 0) #define NUT_AUTO_INCREMENT(x) NUT_INFO(__nut_AUTO_INCREMENT, x, 0)
#define NUT_PRIMARY_AUTO_INCREMENT(x) NUT_PRIMARY_KEY(x) \ #define NUT_PRIMARY_AUTO_INCREMENT(x) NUT_INFO(__nut_PRIMARY_KEY_AI, x, 0)
NUT_AUTO_INCREMENT(x)
#define NUT_DISPLAY_NAME(field, name) NUT_INFO(__nut_DISPLAY, field, name) #define NUT_DISPLAY_NAME(field, name) NUT_INFO(__nut_DISPLAY, field, name)
#define NUT_UNIQUE(x) NUT_INFO(__nut_UNIQUE, x, 0) #define NUT_UNIQUE(x) NUT_INFO(__nut_UNIQUE, x, 0)
#define NUT_LEN(field, len) NUT_INFO(__nut_LEN, field, len) #define NUT_LEN(field, len) NUT_INFO(__nut_LEN, field, len)

View File

@ -27,10 +27,11 @@
#define __FOREIGN_KEYS "foreign_keys" #define __FOREIGN_KEYS "foreign_keys"
#define __nut_FIELD "field" #define __nut_FIELD "field"
#define __nut_NAME_PERFIX "nut_info::"
#define __nut_DB_VERSION "database_version" #define __nut_DB_VERSION "database_version"
#define __nut_NAME_PERFIX "nut_db_key::"
#define __nut_PRIMARY_KEY "primary_key" #define __nut_PRIMARY_KEY "primary_key"
#define __nut_AUTO_INCREMENT "auto_increment" #define __nut_AUTO_INCREMENT "auto_increment"
#define __nut_PRIMARY_KEY_AI "primary_key_ai"
#define __nut_UNIQUE "unique" #define __nut_UNIQUE "unique"
#define __nut_TABLE "table" #define __nut_TABLE "table"
#define __nut_TABLE_NAME "table_name" #define __nut_TABLE_NAME "table_name"

View File

@ -63,7 +63,7 @@ QString PostgreSqlGenerator::fieldType(FieldModel *field)
if(field->isAutoIncrement) if(field->isAutoIncrement)
dbType = "BIGSERIAL"; dbType = "BIGSERIAL";
else else
dbType = "BIGINTEGER"; dbType = "BIGINT";
break; break;
case QVariant::Double: case QVariant::Double:

View File

@ -395,13 +395,13 @@ QString SqlGeneratorBase::join(const QStringList &list, QStringList *order)
QString SqlGeneratorBase::insertRecord(Table *t, QString tableName) QString SqlGeneratorBase::insertRecord(Table *t, QString tableName)
{ {
QString sql = QString(); QString sql = QString();
QString key = t->primaryKey(); QString key = t->isPrimaryKeyAutoIncrement() ? t->primaryKey() : QString();
QStringList values; QStringList values;
foreach (QString f, t->changedProperties()) foreach (QString f, t->changedProperties())
if (f != key) if (f != key)
values.append("'" + t->property(f.toLatin1().data()).toString() values.append(escapeValue(t->property(f.toLatin1().data())));
+ "'");
QString changedPropertiesText = QString(); QString changedPropertiesText = QString();
QSet<QString> props = t->changedProperties(); QSet<QString> props = t->changedProperties();
@ -534,7 +534,7 @@ QString SqlGeneratorBase::selectCommand(const QString &tableName,
Q_UNUSED(take); Q_UNUSED(take);
QString selectText; QString selectText;
if (!fields.isValid) { if (fields.data.count() == 0) {
QSet<TableModel*> tables; QSet<TableModel*> tables;
tables.insert(_database->model().tableByName(tableName)); tables.insert(_database->model().tableByName(tableName));
foreach (RelationModel *rel, joins) foreach (RelationModel *rel, joins)
@ -648,6 +648,27 @@ QString SqlGeneratorBase::updateCommand(const QString &tableName,
return sql; return sql;
} }
QString SqlGeneratorBase::insertCommand(const QString &tableName, const AssignmentPhraseList &assigments)
{
QString fieldNames;
QString values;
foreach (PhraseData *d, assigments.data) {
if (fieldNames != "")
fieldNames.append(", ");
if (values != "")
values.append(", ");
fieldNames.append(d->left->fieldName);
values.append(escapeValue(d->operand));
}
return QString("INSERT INTO %1 (%2) VALUES (%3);")
.arg(tableName)
.arg(fieldNames)
.arg(values);
}
//QString SqlGeneratorBase::selectCommand(SqlGeneratorBase::AgregateType t, //QString SqlGeneratorBase::selectCommand(SqlGeneratorBase::AgregateType t,
// QString agregateArg, // QString agregateArg,
// QString tableName, // QString tableName,
@ -785,7 +806,7 @@ QString SqlGeneratorBase::escapeValue(const QVariant &v) const
break; break;
case QVariant::Uuid: case QVariant::Uuid:
return v.toUuid().toString(); return "'" + v.toUuid().toString() + "'";
break; break;
case QVariant::Char: case QVariant::Char:

View File

@ -109,6 +109,9 @@ public:
virtual QString updateCommand(const QString &tableName, virtual QString updateCommand(const QString &tableName,
const AssignmentPhraseList &assigments, const AssignmentPhraseList &assigments,
const ConditionalPhrase &where); const ConditionalPhrase &where);
virtual QString insertCommand(const QString &tableName,
const AssignmentPhraseList &assigments);
// virtual QString selectCommand(AgregateType t, // virtual QString selectCommand(AgregateType t,
// QString agregateArg, QString tableName, // QString agregateArg, QString tableName,
// QList<WherePhrase> &wheres, // QList<WherePhrase> &wheres,

View File

@ -64,6 +64,9 @@ QString SqliteGenerator::fieldType(FieldModel *field)
else else
dbType = "text"; dbType = "text";
break; break;
case QVariant::Uuid:
dbType = "text";
break;
default: default:
dbType = QString(); dbType = QString();
} }

View File

@ -24,8 +24,6 @@
NUT_BEGIN_NAMESPACE NUT_BEGIN_NAMESPACE
#define LOG(s) qDebug() << __func__ << s
PhraseData::PhraseData() : PhraseData::PhraseData() :
className(""), fieldName(""), className(""), fieldName(""),
type(Field), operatorCond(NotAssign), type(Field), operatorCond(NotAssign),
@ -65,7 +63,6 @@ PhraseData::PhraseData(PhraseData *l, PhraseData::Condition o, QVariant r)
PhraseData *PhraseData::operator =(PhraseData *other) PhraseData *PhraseData::operator =(PhraseData *other)
{ {
LOG("");
other->parents++; other->parents++;
return other; return other;
} }
@ -76,20 +73,6 @@ PhraseData &PhraseData::operator =(PhraseData &other)
return other; return other;
} }
//PhraseData::PhraseData(const PhraseData &other) :
// left(other.left), right(other.right), operand(other.operand),
// operatorCond(other.operatorCond), className(other.className),
// fieldName(other.fieldName), type(other.type), isNot(other.isNot),
// parents(other.parents + 1)
//{ }
//PhraseData::PhraseData(const PhraseData *other) :
// left(other->left), right(other->right), operand(other->operand),
// operatorCond(other->operatorCond), className(other->className),
// fieldName(other->fieldName), type(other->type), isNot(other->isNot),
// parents(other->parents + 1)
//{ }
QString PhraseData::toString() const QString PhraseData::toString() const
{ {
return QString("[%1].%2").arg(className).arg(fieldName); return QString("[%1].%2").arg(className).arg(fieldName);
@ -97,27 +80,10 @@ QString PhraseData::toString() const
PhraseData::~PhraseData() PhraseData::~PhraseData()
{ {
// if (type == WithOther) {
// delete left;
// delete right;
// }
// if (type == WithVariant) {
// if (left)
// delete left;
// }
// if (right && !--right->parents)
// delete right;
// if (left && !--left->parents)
// delete left;
LOG("");
} }
void PhraseData::cleanUp() void PhraseData::cleanUp()
{ {
// cleanUp(this);
} }
void PhraseData::cleanUp(PhraseData *d) void PhraseData::cleanUp(PhraseData *d)
@ -154,12 +120,6 @@ AbstractFieldPhrase::AbstractFieldPhrase(AbstractFieldPhrase &&other)
AbstractFieldPhrase::~AbstractFieldPhrase() AbstractFieldPhrase::~AbstractFieldPhrase()
{ {
if (data) {
LOG(data->toString()) << data->parents;
} else {
LOG("");
}
if (data) { if (data) {
--data->parents; --data->parents;
if (data->parents <= 0) if (data->parents <= 0)
@ -232,14 +192,12 @@ PhraseList::PhraseList() : isValid(false)
PhraseList::PhraseList(const PhraseList &other) : isValid(true) PhraseList::PhraseList(const PhraseList &other) : isValid(true)
{ {
LOG("");
data = qMove(other.data); data = qMove(other.data);
const_cast<PhraseList&>(other).data.clear(); const_cast<PhraseList&>(other).data.clear();
} }
PhraseList::PhraseList(PhraseList &&other) PhraseList::PhraseList(PhraseList &&other)
{ {
LOG("");
data = other.data; data = other.data;
} }
@ -277,7 +235,6 @@ PhraseList::PhraseList(PhraseList *left, const AbstractFieldPhrase *right)
PhraseList::~PhraseList() PhraseList::~PhraseList()
{ {
LOG("");
} }
PhraseList &PhraseList::operator =(const PhraseList &other) PhraseList &PhraseList::operator =(const PhraseList &other)
@ -484,7 +441,6 @@ ConditionalPhrase::ConditionalPhrase(ConditionalPhrase *l,
ConditionalPhrase::~ConditionalPhrase() ConditionalPhrase::~ConditionalPhrase()
{ {
LOG("");
if (data) { if (data) {
data->cleanUp(); data->cleanUp();
if (!--data->parents) if (!--data->parents)
@ -521,7 +477,7 @@ ConditionalPhrase ConditionalPhrase::operator ==(const QVariant &other)
// const_cast<ConditionalPhrase&>(other)); // const_cast<ConditionalPhrase&>(other));
//} //}
#define DECLARE_CONDITIONALPHRASE_OPERATORS(op, cond) \ #define DECLARE_CONDITIONALPHRASE_OPERATORS_IMPL(op, cond) \
ConditionalPhrase operator op(const ConditionalPhrase &l, \ ConditionalPhrase operator op(const ConditionalPhrase &l, \
const ConditionalPhrase &r) \ const ConditionalPhrase &r) \
{ \ { \
@ -570,9 +526,9 @@ ConditionalPhrase operator op(ConditionalPhrase &&l, ConditionalPhrase &&r) \
return p; \ return p; \
} }
DECLARE_CONDITIONALPHRASE_OPERATORS(==, PhraseData::Equal) DECLARE_CONDITIONALPHRASE_OPERATORS_IMPL(==, PhraseData::Equal)
DECLARE_CONDITIONALPHRASE_OPERATORS(||, PhraseData::Or) DECLARE_CONDITIONALPHRASE_OPERATORS_IMPL(||, PhraseData::Or)
DECLARE_CONDITIONALPHRASE_OPERATORS(&&, PhraseData::And) DECLARE_CONDITIONALPHRASE_OPERATORS_IMPL(&&, PhraseData::And)
ConditionalPhrase ConditionalPhrase::operator !() ConditionalPhrase ConditionalPhrase::operator !()
{ {

View File

@ -83,12 +83,14 @@ public:
QVariant min(const FieldPhrase<int> &f); QVariant min(const FieldPhrase<int> &f);
QVariant average(const FieldPhrase<int> &f); QVariant average(const FieldPhrase<int> &f);
QVariant insert(AssignmentPhraseList p);
//data mailpulation //data mailpulation
int update(const AssignmentPhraseList &ph); int update(const AssignmentPhraseList &ph);
// int insert(const AssignmentPhraseList &ph); // int insert(const AssignmentPhraseList &ph);
int remove(); int remove();
QSqlQueryModel *toModal(); QSqlQueryModel *toModel();
//debug purpose //debug purpose
QString sqlCommand() const; QString sqlCommand() const;
@ -121,7 +123,6 @@ template <class T>
Q_OUTOFLINE_TEMPLATE Query<T>::~Query() Q_OUTOFLINE_TEMPLATE Query<T>::~Query()
{ {
Q_D(Query); Q_D(Query);
qDebug() << "~Query";// << d->sql;
delete d; delete d;
} }
@ -223,7 +224,8 @@ Q_OUTOFLINE_TEMPLATE QList<T *> Query<T>::toList(int count)
// if (p == lastP) // if (p == lastP)
// qFatal("NULL Loop detected"); // qFatal("NULL Loop detected");
n = (++n) % levels.count(); ++n;
n = n % levels.count();
if (checked[n]) if (checked[n])
continue; continue;
LevelData &data = levels[n]; LevelData &data = levels[n];
@ -231,13 +233,16 @@ Q_OUTOFLINE_TEMPLATE QList<T *> Query<T>::toList(int count)
// check if key value is changed // check if key value is changed
if (data.lastKeyValue == q.value(data.keyFiledname)) { if (data.lastKeyValue == q.value(data.keyFiledname)) {
--p; --p;
qDebug() << "key os not changed for" << data.keyFiledname;
continue; continue;
} }
// check if master if current table has processed // check if master if current table has processed
foreach (int m, data.masters) foreach (int m, data.masters)
if (!checked[m]) if (!checked[m]) {
qDebug() << "row is checked";
continue; continue;
}
checked[n] = true; checked[n] = true;
--p; --p;
@ -257,6 +262,8 @@ Q_OUTOFLINE_TEMPLATE QList<T *> Query<T>::toList(int count)
if (!table) if (!table)
qFatal("Could not create instance of %s", qFatal("Could not create instance of %s",
qPrintable(data.table->name())); qPrintable(data.table->name()));
qDebug() << data.table->name() << "created";
} }
QStringList childFields = data.table->fieldsNames(); QStringList childFields = data.table->fieldsNames();
@ -327,7 +334,7 @@ Q_OUTOFLINE_TEMPLATE T *Query<T>::first()
if (list.count()) if (list.count())
return list.first(); return list.first();
else else
return 0; return nullptr;
} }
template <class T> template <class T>
@ -404,6 +411,17 @@ Q_OUTOFLINE_TEMPLATE QVariant Query<T>::average(const FieldPhrase<int> &f)
return 0; return 0;
} }
template<class T>
Q_OUTOFLINE_TEMPLATE QVariant Query<T>::insert(AssignmentPhraseList p)
{
Q_D(Query);
d->sql = d->database->sqlGenertor()
->insertCommand(d->tableName, p);
QSqlQuery q = d->database->exec(d->sql);
return q.lastInsertId();
}
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)
{ {
@ -524,7 +542,7 @@ Q_OUTOFLINE_TEMPLATE int Query<T>::remove()
} }
template <class T> template <class T>
Q_OUTOFLINE_TEMPLATE QSqlQueryModel *Query<T>::toModal() Q_OUTOFLINE_TEMPLATE QSqlQueryModel *Query<T>::toModel()
{ {
Q_D(Query); Q_D(Query);
@ -533,12 +551,14 @@ Q_OUTOFLINE_TEMPLATE QSqlQueryModel *Query<T>::toModal()
d->fieldPhrase, d->fieldPhrase,
d->wherePhrase, d->orderPhrase, d->relations, d->wherePhrase, d->orderPhrase, d->relations,
d->skip, d->take); d->skip, d->take);
qDebug() << d->sql;
DatabaseModel dbModel = d->database->model(); DatabaseModel dbModel = d->database->model();
QSqlQueryModel *model = new QSqlQueryModel; QSqlQueryModel *model = new QSqlQueryModel;
model->setQuery(d->sql, d->database->database()); model->setQuery(d->sql, d->database->database());
int fieldIndex = 0; int fieldIndex = 0;
if (d->fieldPhrase.data.count()) {
foreach (const PhraseData *pd, d->fieldPhrase.data) { foreach (const PhraseData *pd, d->fieldPhrase.data) {
QString displayName = dbModel.tableByClassName(pd->className) QString displayName = dbModel.tableByClassName(pd->className)
->field(pd->fieldName)->displayName; ->field(pd->fieldName)->displayName;
@ -549,6 +569,14 @@ Q_OUTOFLINE_TEMPLATE QSqlQueryModel *Query<T>::toModal()
Qt::Horizontal, Qt::Horizontal,
displayName); displayName);
} }
} else {
TableModel *tbl = d->database->model().tableByName(d->tableName);
foreach (FieldModel *f, tbl->fields()) {
model->setHeaderData(fieldIndex++,
Qt::Horizontal,
f->displayName);
}
}
return model; return model;
} }

View File

@ -74,7 +74,8 @@ void Table::propertyChanged(QString propName)
if (!myModel) if (!myModel)
qFatal ("model for this class not found"); qFatal ("model for this class not found");
if (propName == primaryKey()) foreach (FieldModel *f, myModel->fields())
if(f->isPrimaryKey && propName == f->name && f->isAutoIncrement)
return; return;
_changedProperties.insert(propName); _changedProperties.insert(propName);

View File

@ -39,7 +39,7 @@ class NUT_EXPORT Table : public QObject
Q_OBJECT Q_OBJECT
public: public:
explicit Table(QObject *parentTableSet = 0); explicit Table(QObject *parentTableSet = nullptr);
enum Status{ enum Status{
NewCreated, NewCreated,

View File

@ -156,22 +156,22 @@ bool TableModel::operator !=(const TableModel &t) const
return !(*this == t); return !(*this == t);
} }
bool TableModel::checkClassInfo(const QMetaClassInfo &classInfo, //bool TableModel::checkClassInfo(const QMetaClassInfo &classInfo,
QString &type, QString &name, QString &value) // QString &type, QString &name, QString &value)
{ //{
if (!QString(classInfo.name()).startsWith(__nut_NAME_PERFIX)) { // if (!QString(classInfo.name()).startsWith(__nut_NAME_PERFIX)) {
return false; // return false;
} else { // } else {
QStringList parts = QString(classInfo.value()).split("\n"); // QStringList parts = QString(classInfo.value()).split("\n");
if (parts.count() != 3) // if (parts.count() != 3)
return false; // return false;
type = parts[0]; // type = parts[0];
name = parts[1]; // name = parts[1];
value = parts[2]; // value = parts[2];
return true; // return true;
} // }
} //}
TableModel::TableModel(int typeId, QString tableName) TableModel::TableModel(int typeId, QString tableName)
{ {
@ -196,7 +196,7 @@ TableModel::TableModel(int typeId, QString tableName)
QString name; QString name;
QString value; QString value;
if (!checkClassInfo(tableMetaObject->classInfo(j), if (!nutClassInfoString(tableMetaObject->classInfo(j),
type, name, value)) { type, name, value)) {
continue; continue;
} }
@ -227,7 +227,7 @@ TableModel::TableModel(int typeId, QString tableName)
QString name; QString name;
QString value; QString value;
if (!checkClassInfo(tableMetaObject->classInfo(j), if (!nutClassInfoString(tableMetaObject->classInfo(j),
type, name, value)) { type, name, value)) {
continue; continue;
} }
@ -248,23 +248,27 @@ TableModel::TableModel(int typeId, QString tableName)
FieldModel *f = field(name); FieldModel *f = field(name);
if(!f) if (!f)
continue; continue;
if(type == __nut_LEN) if (type == __nut_LEN)
f->length = value.toInt(); f->length = value.toInt();
else if(type == __nut_NOT_NULL) else if (type == __nut_NOT_NULL)
f->notNull = true; f->notNull = true;
else if(type == __nut_DEFAULT_VALUE) else if (type == __nut_DEFAULT_VALUE)
f->defaultValue = value; f->defaultValue = value;
else if(type == __nut_PRIMARY_KEY) else if (type == __nut_PRIMARY_KEY)
f->isPrimaryKey = true; f->isPrimaryKey = true;
else if(type == __nut_AUTO_INCREMENT) else if (type == __nut_AUTO_INCREMENT)
f->isAutoIncrement = true; f->isAutoIncrement = true;
else if(type == __nut_UNIQUE) else if (type == __nut_UNIQUE)
f->isUnique = true; f->isUnique = true;
else if(type == __nut_DISPLAY) else if (type == __nut_DISPLAY)
f->displayName = value.mid(1, value.length() - 2); f->displayName = value.mid(1, value.length() - 2);
else if (type == __nut_PRIMARY_KEY_AI) {
f->isPrimaryKey = true;
f->isAutoIncrement = true;
}
} }
if(!findByTypeId(typeId) && !tableName.isNull()) if(!findByTypeId(typeId) && !tableName.isNull())

View File

@ -138,8 +138,8 @@ private:
QList<FieldModel*> _fields; QList<FieldModel*> _fields;
QList<RelationModel*> _foreignKeys; QList<RelationModel*> _foreignKeys;
static QSet<TableModel*>_allModels; static QSet<TableModel*>_allModels;
bool checkClassInfo(const QMetaClassInfo &classInfo, // bool checkClassInfo(const QMetaClassInfo &classInfo,
QString &type, QString &name, QString &value); // QString &type, QString &name, QString &value);
}; };
NUT_END_NAMESPACE NUT_END_NAMESPACE

View File

@ -21,10 +21,10 @@
#ifndef TABLESET_H #ifndef TABLESET_H
#define TABLESET_H #define TABLESET_H
#include <QtCore/qglobal.h> #include <QtCore/QtGlobal>
#include <QtCore/QVariant>
#include <QtCore/QMetaMethod> #include <QtCore/QMetaMethod>
#include <QtCore/QMetaType> #include <QtCore/QMetaType>
#include <QtCore/QVariant>
#include <QtSql/QSqlQuery> #include <QtSql/QSqlQuery>
#include "tablesetbase_p.h" #include "tablesetbase_p.h"
@ -52,6 +52,7 @@ public:
int length() const; int length() const;
T *at(int i) const; T *at(int i) const;
const T &operator[](int i) const; const T &operator[](int i) const;
Query<T> *query(); Query<T> *query();
Query<T> *query(bool autoDelete); Query<T> *query(bool autoDelete);
}; };

View File

@ -25,12 +25,14 @@
NUT_BEGIN_NAMESPACE NUT_BEGIN_NAMESPACE
TableSetBase::TableSetBase(Database *parent) : QObject(parent), _database(parent), _table(0) TableSetBase::TableSetBase(Database *parent) : QObject(parent), _database(parent), _table(0),
_tableName(QString())
{ {
parent->add(this); parent->add(this);
} }
TableSetBase::TableSetBase(Table *parent) : QObject(parent), _database(0), _table(parent) TableSetBase::TableSetBase(Table *parent) : QObject(parent), _database(0), _table(parent),
_tableName(QString())
{ {
parent->add(this); parent->add(this);
} }

View File

@ -22,17 +22,20 @@
.arg(timer.elapsed() / 1000.) \ .arg(timer.elapsed() / 1000.) \
.arg(__func__) .arg(__func__)
#define REGISTER(x) qDebug() << #x << "type id:" << qRegisterMetaType<x*>()
MainTest::MainTest(QObject *parent) : QObject(parent) MainTest::MainTest(QObject *parent) : QObject(parent)
{ {
} }
void MainTest::initTestCase() void MainTest::initTestCase()
{ {
qDebug() << "User type id:" << qRegisterMetaType<User*>(); //register all entities with Qt-MetaType mechanism
qDebug() << "Post type id:" << qRegisterMetaType<Post*>(); REGISTER(User);
qDebug() << "Score type id:" << qRegisterMetaType<Score*>(); REGISTER(Post);
qDebug() << "Comment type id:" << qRegisterMetaType<Comment*>(); REGISTER(Score);
qDebug() << "DB type id:" << qRegisterMetaType<WeblogDatabase*>(); REGISTER(Comment);
REGISTER(WeblogDatabase);
db.setDriver(DRIVER); db.setDriver(DRIVER);
db.setHostName(HOST); db.setHostName(HOST);
@ -41,11 +44,12 @@ void MainTest::initTestCase()
db.setPassword(PASSWORD); db.setPassword(PASSWORD);
bool ok = db.open(); bool ok = db.open();
db.commentTable()->query()->remove();
db.postTable()->query()->remove();
QTEST_ASSERT(ok); QTEST_ASSERT(ok);
db.comments()->query()->remove();
db.posts()->query()->remove();
db.users()->query()->remove();
db.scores()->query()->remove();
} }
void MainTest::dataScheema() void MainTest::dataScheema()
@ -61,9 +65,10 @@ void MainTest::dataScheema()
void MainTest::createUser() void MainTest::createUser()
{ {
user = new User; user = new User;
user->setId(QUuid::createUuid());
user->setUsername("admin"); user->setUsername("admin");
user->setPassword("123456"); user->setPassword("123456");
db.userTable()->append(user); db.users()->append(user);
db.saveChanges(); db.saveChanges();
} }
@ -73,11 +78,13 @@ void MainTest::createPost()
Post *newPost = new Post; Post *newPost = new Post;
newPost->setTitle("post title"); newPost->setTitle("post title");
newPost->setSaveDate(QDateTime::currentDateTime()); newPost->setSaveDate(QDateTime::currentDateTime());
newPost->setPublic(false);
db.postTable()->append(newPost); db.posts()->append(newPost);
for(int i = 0 ; i < 3; i++){ for(int i = 0 ; i < 3; i++){
Comment *comment = new Comment; Comment *comment = new Comment;
comment->setId(QUuid::createUuid());
comment->setMessage("comment #" + QString::number(i)); comment->setMessage("comment #" + QString::number(i));
comment->setSaveDate(QDateTime::currentDateTime()); comment->setSaveDate(QDateTime::currentDateTime());
comment->setAuthorId(user->id()); comment->setAuthorId(user->id());
@ -100,30 +107,32 @@ void MainTest::createPost()
void MainTest::createPost2() void MainTest::createPost2()
{ {
Post *newPost = new Post; //create post on the fly
newPost->setTitle("post title"); QVariant postIdVar = db.posts()->query()->insert(
newPost->setSaveDate(QDateTime::currentDateTime()); (Post::titleField() = "This is a sample")
& (Post::isPublicField() = true));
db.postTable()->append(newPost); QTEST_ASSERT(postIdVar.type() == QVariant::LongLong);
db.saveChanges(); int postId = postIdVar.toInt();
for(int i = 0 ; i < 3; i++){ for(int i = 0 ; i < 3; i++){
Comment *comment = new Comment; Comment *comment = new Comment;
comment->setId(QUuid::createUuid());
comment->setMessage("comment #" + QString::number(i + 2)); comment->setMessage("comment #" + QString::number(i + 2));
comment->setSaveDate(QDateTime::currentDateTime()); comment->setSaveDate(QDateTime::currentDateTime());
comment->setAuthor(user); comment->setAuthor(user);
comment->setPostId(newPost->id()); //join child to master by id
db.commentTable()->append(comment); comment->setPostId(postId);
db.comments()->append(comment);
} }
db.saveChanges(); db.saveChanges();
QTEST_ASSERT(newPost->id() != 0); QTEST_ASSERT(postId != 0);
qDebug() << "New post2 inserted with id:" << newPost->id();
} }
void MainTest::updatePostOnTheFly() void MainTest::updatePostOnTheFly()
{ {
auto c = db.postTable()->query() auto c = db.posts()->query()
->where(Post::idField() == postId) ->where(Post::idField() == postId)
->update(Post::titleField() = "New title"); ->update(Post::titleField() = "New title");
@ -132,19 +141,22 @@ void MainTest::updatePostOnTheFly()
void MainTest::selectPublicts() void MainTest::selectPublicts()
{ {
auto q = db.postTable()->query() auto q = db.posts()->query()
->where(Post::isPublicField()) ->where(Post::isPublicField())
->toList(); ->count();
auto q2 = db.postTable()->query() auto q2 = db.posts()->query()
->where(!Post::isPublicField()) ->where(!Post::isPublicField())
->toList(); ->count();
QTEST_ASSERT(q == 1);
QTEST_ASSERT(q2 == 1);
} }
void MainTest::selectPosts() void MainTest::selectPosts()
{ {
auto q = db.postTable()->query() auto q = db.posts()->query()
->join<Comment>()//Comment::authorIdField() == Post::idField()) ->join<Comment>()
->orderBy(!Post::saveDateField() | Post::bodyField()) ->orderBy(!Post::saveDateField() | Post::bodyField())
->setWhere(Post::idField() == postId); ->setWhere(Post::idField() == postId);
@ -155,6 +167,7 @@ void MainTest::selectPosts()
PRINT(posts.length()); PRINT(posts.length());
PRINT(posts.at(0)->comments()->length()); PRINT(posts.at(0)->comments()->length());
QTEST_ASSERT(posts.length() == 1); QTEST_ASSERT(posts.length() == 1);
qDebug() << posts.at(0)->comments()->length();
QTEST_ASSERT(posts.at(0)->comments()->length() == 3); QTEST_ASSERT(posts.at(0)->comments()->length() == 3);
QTEST_ASSERT(posts.at(0)->title() == "post title"); QTEST_ASSERT(posts.at(0)->title() == "post title");
@ -166,7 +179,7 @@ void MainTest::selectPosts()
void MainTest::selectScoreAverage() void MainTest::selectScoreAverage()
{ {
auto a = db.scoreTable()->query() auto a = db.scores()->query()
->join<Post>() ->join<Post>()
->setWhere(Post::idField() == 1) ->setWhere(Post::idField() == 1)
->average(Score::scoreField()); ->average(Score::scoreField());
@ -175,7 +188,7 @@ void MainTest::selectScoreAverage()
void MainTest::selectFirst() void MainTest::selectFirst()
{ {
auto posts = db.postTable()->query() auto posts = db.posts()->query()
->first(); ->first();
QTEST_ASSERT(posts != Q_NULLPTR); QTEST_ASSERT(posts != Q_NULLPTR);
@ -183,7 +196,7 @@ void MainTest::selectFirst()
void MainTest::selectPostsWithoutTitle() void MainTest::selectPostsWithoutTitle()
{ {
auto q = db.postTable()->query(); auto q = db.posts()->query();
q->setWhere(Post::titleField().isNull()); q->setWhere(Post::titleField().isNull());
auto count = q->count(); auto count = q->count();
QTEST_ASSERT(count == 0); QTEST_ASSERT(count == 0);
@ -191,9 +204,9 @@ void MainTest::selectPostsWithoutTitle()
void MainTest::selectPostIds() void MainTest::selectPostIds()
{ {
auto q = db.postTable()->query(); auto q = db.posts()->query();
auto ids = q->select(Post::idField()); auto ids = q->select(Post::idField());
qDebug() << q->sqlCommand(); qDebug() << ids.count();
QTEST_ASSERT(ids.count() == 2); QTEST_ASSERT(ids.count() == 2);
} }
@ -207,11 +220,11 @@ void MainTest::testDate()
newPost->setTitle("post title"); newPost->setTitle("post title");
newPost->setSaveDate(d); newPost->setSaveDate(d);
db.postTable()->append(newPost); db.posts()->append(newPost);
db.saveChanges(true); db.saveChanges(true);
auto q = db.postTable()->query() auto q = db.posts()->query()
->setWhere(Post::idField() == newPost->id()) ->setWhere(Post::idField() == newPost->id())
->first(); ->first();
@ -221,7 +234,7 @@ void MainTest::testDate()
void MainTest::join() void MainTest::join()
{ {
TIC(); TIC();
auto q = db.commentTable()->query() auto q = db.comments()->query()
->join<User>() ->join<User>()
->join<Post>(); ->join<Post>();
@ -236,24 +249,24 @@ void MainTest::join()
void MainTest::selectWithInvalidRelation() void MainTest::selectWithInvalidRelation()
{ {
auto q = db.postTable()->query(); auto q = db.posts()->query();
q->join("Invalid_Class_Name"); q->join("Invalid_Class_Name");
q->toList(); q->toList();
} }
void MainTest::modifyPost() void MainTest::modifyPost()
{ {
auto q = db.postTable()->query(); auto q = db.posts()->query();
q->setWhere(Post::idField() == postId); q->setWhere(Post::idField() == postId);
Post *post = q->first(); Post *post = q->first();
QTEST_ASSERT(post != 0); QTEST_ASSERT(post != nullptr);
post->setTitle("new name"); post->setTitle("new name");
db.saveChanges(); db.saveChanges();
q = db.postTable()->query() q = db.posts()->query()
->setWhere(Post::idField() == postId); ->setWhere(Post::idField() == postId);
post = q->first(); post = q->first();
@ -263,10 +276,10 @@ void MainTest::modifyPost()
void MainTest::emptyDatabase() void MainTest::emptyDatabase()
{ {
auto commentsCount = db.commentTable()->query()->remove(); // auto commentsCount = db.comments()->query()->remove();
auto postsCount = db.postTable()->query()->remove(); // auto postsCount = db.posts()->query()->remove();
QTEST_ASSERT(postsCount == 3); // QTEST_ASSERT(postsCount == 3);
QTEST_ASSERT(commentsCount == 6); // QTEST_ASSERT(commentsCount == 6);
} }
void MainTest::cleanupTestCase() void MainTest::cleanupTestCase()
@ -274,8 +287,10 @@ void MainTest::cleanupTestCase()
post->deleteLater(); post->deleteLater();
user->deleteLater(); user->deleteLater();
//release models before exiting
qDeleteAll(TableModel::allModels()); qDeleteAll(TableModel::allModels());
DatabaseModel::deleteAllModels();
PRINT_FORM(db);
} }
QTEST_MAIN(MainTest) QTEST_MAIN(MainTest)

View File

@ -16,7 +16,7 @@ class MainTest : public QObject
User *user; User *user;
public: public:
explicit MainTest(QObject *parent = 0); explicit MainTest(QObject *parent = nullptr);
signals: signals:

View File

@ -14,7 +14,7 @@ class MainTest : public QObject
Post *post; Post *post;
Query<Post> *q; Query<Post> *q;
public: public:
explicit MainTest(QObject *parent = 0); explicit MainTest(QObject *parent = nullptr);
signals: signals:

View File

@ -14,7 +14,7 @@ class MainTest : public QObject
Post *post; Post *post;
Query<Post> *q; Query<Post> *q;
public: public:
explicit MainTest(QObject *parent = 0); explicit MainTest(QObject *parent = nullptr);
signals: signals:

View File

@ -3,6 +3,7 @@
#include <QtCore/qglobal.h> #include <QtCore/qglobal.h>
#include <QtCore/QDateTime> #include <QtCore/QDateTime>
#include <QtCore/QUuid>
#include "table.h" #include "table.h"
#ifdef NUT_NAMESPACE #ifdef NUT_NAMESPACE
@ -15,17 +16,17 @@ class Comment : public Table
{ {
Q_OBJECT Q_OBJECT
NUT_PRIMARY_AUTO_INCREMENT(id) NUT_PRIMARY_KEY(id)
NUT_DECLARE_FIELD(int, id, id, setId) NUT_DECLARE_FIELD(QUuid, id, id, setId)
NUT_DECLARE_FIELD(QString, message, message, setMessage) NUT_DECLARE_FIELD(QString, message, message, setMessage)
NUT_DECLARE_FIELD(QDateTime, saveDate, saveDate, setSaveDate) NUT_DECLARE_FIELD(QDateTime, saveDate, saveDate, setSaveDate)
NUT_DECLARE_FIELD(qreal, point, point, setPoint) NUT_DECLARE_FIELD(qreal, point, point, setPoint)
NUT_FOREGION_KEY(Post, int, post, post, setPost) NUT_FOREGION_KEY(Post, int, post, post, setPost)
NUT_FOREGION_KEY(User, int, author, author, setAuthor) NUT_FOREGION_KEY(User, QUuid, author, author, setAuthor)
public: public:
Q_INVOKABLE explicit Comment(QObject *parentTableSet = 0); Q_INVOKABLE explicit Comment(QObject *parentTableSet = nullptr);
}; };
Q_DECLARE_METATYPE(Comment*) Q_DECLARE_METATYPE(Comment*)

View File

@ -1,6 +1,12 @@
#ifndef CONSTS_H #ifndef CONSTS_H
#define CONSTS_H #define CONSTS_H
#define PRINT(x) qDebug() << #x "=" << x;
#define TIC() QElapsedTimer timer; timer.start()
#define TOC() qDebug() << QString("Elapsed time: %1ms for %2") \
.arg(timer.elapsed() / 1000.) \
.arg(__func__)
//#define DRIVER "QPSQL" //#define DRIVER "QPSQL"
//#define HOST "127.0.0.1" //#define HOST "127.0.0.1"
//#define DATABASE "nutdb2" //#define DATABASE "nutdb2"
@ -9,7 +15,7 @@
#define DRIVER "QSQLITE" #define DRIVER "QSQLITE"
#define HOST "127.0.0.1" #define HOST "127.0.0.1"
#define DATABASE "nutdb" #define DATABASE "nutdb1"
#define USERNAME "root" #define USERNAME "root"
#define PASSWORD "onlyonlyi" #define PASSWORD "onlyonlyi"
@ -19,4 +25,25 @@
//#define USERNAME "sa" //#define USERNAME "sa"
//#define PASSWORD "qwe123!@#" //#define PASSWORD "qwe123!@#"
#ifdef Q_OS_LINUX
# define OS "Linux"
#elif defined(Q_OS_WIN)
# define OS "Windows"
#elif defined(Q_OS_OSX)
# define OS "macOS"
#else
# define OS "Unknown"
#endif
#define PRINT_FORM(db) \
qDebug() << "\n\n****************************" \
<< "\nAll tests passed," \
<< "please fill in bellow form and email it to me at" \
<< "hamed.masafi@gmail.com" \
<< "\n\tDriver:" << db.driver() \
<< "\n\tOS: " OS " (version: ________)" \
<< "\n\tQt version: " QT_VERSION_STR \
<< "\n\tTest:" << metaObject()->className() \
<< "\n****************************\n";
#endif // CONSTS_H #endif // CONSTS_H

View File

@ -17,8 +17,8 @@ class User : public Nut::Table
{ {
Q_OBJECT Q_OBJECT
NUT_PRIMARY_AUTO_INCREMENT(id) NUT_PRIMARY_KEY(id)
NUT_DECLARE_FIELD(int, id, id, setId) NUT_DECLARE_FIELD(QUuid, id, id, setId)
NUT_NOT_NULL(username) NUT_NOT_NULL(username)
NUT_LEN(username, 50) NUT_LEN(username, 50)
@ -32,7 +32,7 @@ class User : public Nut::Table
NUT_DECLARE_CHILD_TABLE(Score, scores) NUT_DECLARE_CHILD_TABLE(Score, scores)
public: public:
Q_INVOKABLE User(QObject *parentTableSet = 0); Q_INVOKABLE User(QObject *parentTableSet = nullptr);
}; };
Q_DECLARE_METATYPE(User*) Q_DECLARE_METATYPE(User*)

View File

@ -8,9 +8,9 @@
#include "weblogdatabase.h" #include "weblogdatabase.h"
WeblogDatabase::WeblogDatabase() : Database(), WeblogDatabase::WeblogDatabase() : Database(),
m_postTable(new TableSet<Post>(this)), m_posts(new TableSet<Post>(this)),
m_commentTable(new TableSet<Comment>(this)), m_comments(new TableSet<Comment>(this)),
m_userTable(new TableSet<User>(this)), m_users(new TableSet<User>(this)),
m_scoreTable(new TableSet<Score>(this)) m_scores(new TableSet<Score>(this))
{ {
} }

View File

@ -17,10 +17,10 @@ class WeblogDatabase : public Database
NUT_DB_VERSION(1) NUT_DB_VERSION(1)
NUT_DECLARE_TABLE(Post, post) NUT_DECLARE_TABLE(Post, posts)
NUT_DECLARE_TABLE(Comment, comment) NUT_DECLARE_TABLE(Comment, comments)
NUT_DECLARE_TABLE(User, user) NUT_DECLARE_TABLE(User, users)
NUT_DECLARE_TABLE(Score, score) NUT_DECLARE_TABLE(Score, scores)
public: public:
WeblogDatabase(); WeblogDatabase();

View File

@ -21,7 +21,7 @@ void MainTest::no1()
FieldPhrase<QString> name("main", "name"); FieldPhrase<QString> name("main", "name");
FieldPhrase<QString> last_name("main", "last_name"); FieldPhrase<QString> last_name("main", "last_name");
FieldPhrase<QDate> date("main", "date"); FieldPhrase<QDate> date("main", "date");
auto w = id == 4 && name == "salam"; auto w = (id == 4 && name == "hi");
} }
QTEST_MAIN(MainTest) QTEST_MAIN(MainTest)

View File

@ -11,7 +11,7 @@ class MainTest : public QObject
Q_OBJECT Q_OBJECT
public: public:
explicit MainTest(QObject *parent = 0); explicit MainTest(QObject *parent = nullptr);
signals: signals:

63
test/quuid/maintest.cpp Normal file
View File

@ -0,0 +1,63 @@
#include <QtTest>
#include <QJsonDocument>
#include <QSqlError>
#include <QDebug>
#include <QElapsedTimer>
#include "consts.h"
#include "maintest.h"
#include "query.h"
#include "tableset.h"
#include "tablemodel.h"
#include "test.h"
MainTest::MainTest(QObject *parent) : QObject(parent)
{
}
void MainTest::initTestCase()
{
qDebug() << "Test type id:" << qRegisterMetaType<Test*>();
qDebug() << "DB type id:" << qRegisterMetaType<TestDatabase*>();
db.setDriver(DRIVER);
db.setHostName(HOST);
db.setDatabaseName("nut_tst_quuid");
db.setUserName(USERNAME);
db.setPassword(PASSWORD);
bool ok = db.open();
db.tests()->query()->remove();
QTEST_ASSERT(ok);
}
void MainTest::add()
{
TIC();
QUuid uuid = QUuid::createUuid();
Test t;
t.setId(uuid);
t.setUsername("test username");
db.tests()->append(&t);
db.saveChanges();
TOC();
Test *t2 = db.tests()->query()
->where(Test::idField() == uuid)
->first();
TOC();
QTEST_ASSERT(t2->id() == uuid);
}
void MainTest::cleanupTestCase()
{
qDeleteAll(Nut::TableModel::allModels());
// Nut::DatabaseModel::deleteAllModels();
}
QTEST_MAIN(MainTest)

26
test/quuid/maintest.h Normal file
View File

@ -0,0 +1,26 @@
#ifndef MAINTEST_H
#define MAINTEST_H
#include <QtCore/QObject>
#include <QtCore/qglobal.h>
#include "testdatabase.h"
class Test;
class MainTest : public QObject
{
Q_OBJECT
TestDatabase db;
public:
explicit MainTest(QObject *parent = 0);
signals:
private slots:
void initTestCase();
void add();
void cleanupTestCase();
};
#endif // MAINTEST_H

6
test/quuid/test.cpp Normal file
View File

@ -0,0 +1,6 @@
#include "test.h"
Test::Test(QObject *parentTableSet)
{
}

25
test/quuid/test.h Normal file
View File

@ -0,0 +1,25 @@
#ifndef TEST_H
#define TEST_H
#include <QUuid>
#include "table.h"
class Test : public Nut::Table
{
Q_OBJECT
NUT_PRIMARY_KEY(id)
NUT_DECLARE_FIELD(QUuid, id, id, setId)
NUT_NOT_NULL(username)
NUT_LEN(username, 50)
NUT_DECLARE_FIELD(QString, username, username, setUsername)
public:
Q_INVOKABLE Test(QObject *parentTableSet = 0);
};
Q_DECLARE_METATYPE(Test*)
#endif // TEST_H

View File

@ -0,0 +1,8 @@
#include "testdatabase.h"
#include "test.h"
TestDatabase::TestDatabase(QObject *parent)
: Database(parent), m_tests(new Nut::TableSet<Test>(this))
{
}

18
test/quuid/testdatabase.h Normal file
View File

@ -0,0 +1,18 @@
#ifndef TESTDATABASE_H
#define TESTDATABASE_H
#include <Database>
class Test;
class TestDatabase : public Nut::Database
{
Q_OBJECT
NUT_DB_VERSION(1)
NUT_DECLARE_TABLE(Test, tests)
public:
TestDatabase(QObject *parent = nullptr);
};
#endif // TESTDATABASE_H

20
test/quuid/tst_quuid.pro Normal file
View File

@ -0,0 +1,20 @@
QT += qml quick testlib sql
QT -= gui
TARGET = tst_nut
TEMPLATE = app
CONFIG += warn_on qmltestcase c++11
INCLUDEPATH += $$PWD/../../src $$PWD/../common
include(../../nut.pri)
IMPORTPATH += $$OUT_PWD/../src/imports
SOURCES += \
maintest.cpp \
testdatabase.cpp \
test.cpp
HEADERS += \
maintest.h \
../common/consts.h \
testdatabase.h \
test.h