commit
e71a7ac2ed
|
|
@ -61,4 +61,10 @@ if(post) {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Donate
|
||||||
|
Butcoin address: 1Dn1WHKkaxanXe4cTGDk4cFRRABxLUpEVj
|
||||||
|
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
For more information read [Wiki](wiki).
|
For more information read [Wiki](wiki).
|
||||||
|
|
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 403 B |
78
nut.qbs
78
nut.qbs
|
|
@ -1,39 +1,53 @@
|
||||||
import qbs
|
import qbs
|
||||||
|
|
||||||
Product {
|
Project {
|
||||||
type: "staticlibrary"
|
// StaticLibrary {
|
||||||
name: "nut"
|
// name: "nut_static"
|
||||||
Depends { name: 'cpp' }
|
// files: [
|
||||||
Depends { name: "Qt.core" }
|
// "src/*.h",
|
||||||
Depends { name: "Qt.sql" }
|
// "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 {
|
// Export {
|
||||||
Depends { name: "cpp" }
|
// Depends { name: "cpp" }
|
||||||
|
// Depends { name: "Qt.core" }
|
||||||
|
// Depends { name: "Qt.sql" }
|
||||||
|
// cpp.includePaths: [
|
||||||
|
// product.sourceDirectory + "/src",
|
||||||
|
// product.sourceDirectory + "/include"
|
||||||
|
// ]
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
DynamicLibrary {
|
||||||
|
name: "nut"
|
||||||
|
files: [
|
||||||
|
"src/*.h",
|
||||||
|
"src/*.cpp",
|
||||||
|
"src/generators/*.h",
|
||||||
|
"src/generators/*.cpp"
|
||||||
|
]
|
||||||
|
|
||||||
|
Depends { name: 'cpp' }
|
||||||
Depends { name: "Qt.core" }
|
Depends { name: "Qt.core" }
|
||||||
Depends { name: "Qt.sql" }
|
Depends { name: "Qt.sql" }
|
||||||
cpp.includePaths: [
|
|
||||||
product.sourceDirectory + "/src",
|
|
||||||
product.sourceDirectory + "/include"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
files: [
|
Group { qbs.install: true; fileTagsFilter: product.type;}
|
||||||
"src/tableset.cpp",
|
|
||||||
"src/query.cpp",
|
Export {
|
||||||
"src/databasemodel.cpp",
|
Depends { name: "cpp" }
|
||||||
"src/tablesetbase.cpp",
|
Depends { name: "Qt.core" }
|
||||||
"src/changelogtable.cpp",
|
Depends { name: "Qt.sql" }
|
||||||
"src/querybase.cpp",
|
cpp.includePaths: [
|
||||||
"src/tablemodel.cpp",
|
product.sourceDirectory + "/src",
|
||||||
"src/wherephrase.cpp",
|
product.sourceDirectory + "/include"
|
||||||
"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"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
|
|
||||||
104
src/defines.h
104
src/defines.h
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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"
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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 !()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
58
src/query.h
58
src/query.h
|
|
@ -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,21 +551,31 @@ 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;
|
||||||
foreach (const PhraseData *pd, d->fieldPhrase.data) {
|
|
||||||
QString displayName = dbModel.tableByClassName(pd->className)
|
|
||||||
->field(pd->fieldName)->displayName;
|
|
||||||
|
|
||||||
qDebug() << "Display name for"<<pd->className<<pd->fieldName
|
if (d->fieldPhrase.data.count()) {
|
||||||
<<"="<<displayName;
|
foreach (const PhraseData *pd, d->fieldPhrase.data) {
|
||||||
model->setHeaderData(fieldIndex++,
|
QString displayName = dbModel.tableByClassName(pd->className)
|
||||||
Qt::Horizontal,
|
->field(pd->fieldName)->displayName;
|
||||||
displayName);
|
|
||||||
|
qDebug() << "Display name for"<<pd->className<<pd->fieldName
|
||||||
|
<<"="<<displayName;
|
||||||
|
model->setHeaderData(fieldIndex++,
|
||||||
|
Qt::Horizontal,
|
||||||
|
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;
|
||||||
|
|
|
||||||
|
|
@ -74,8 +74,9 @@ 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())
|
||||||
return;
|
if(f->isPrimaryKey && propName == f->name && f->isAutoIncrement)
|
||||||
|
return;
|
||||||
|
|
||||||
_changedProperties.insert(propName);
|
_changedProperties.insert(propName);
|
||||||
if (_status == FeatchedFromDB)
|
if (_status == FeatchedFromDB)
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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())
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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*)
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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*)
|
||||||
|
|
|
||||||
|
|
@ -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))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
@ -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
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
#include "test.h"
|
||||||
|
|
||||||
|
Test::Test(QObject *parentTableSet)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -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
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
#include "testdatabase.h"
|
||||||
|
#include "test.h"
|
||||||
|
|
||||||
|
TestDatabase::TestDatabase(QObject *parent)
|
||||||
|
: Database(parent), m_tests(new Nut::TableSet<Test>(this))
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
Loading…
Reference in New Issue