diff --git a/src/defines.h b/src/defines.h index 21a4bad..60b9d1c 100644 --- a/src/defines.h +++ b/src/defines.h @@ -33,15 +33,15 @@ #endif #define NUT_INFO(type, name, value) \ - Q_CLASSINFO(__nut_NAME_PERFIX #type #name #value, #value) + Q_CLASSINFO(__nut_NAME_PERFIX #type #name #value, #type "\n" #name "\n" #value) // Database //TODO: remove minor version #define NUT_DB_VERSION(version) \ - Q_CLASSINFO(QT_STRINGIFY(__nut_NAME_PERFIX __nut_DB_VERSION), #version) + NUT_INFO(__nut_DB_VERSION, version, 0) #define NUT_DECLARE_TABLE(type, name) \ - Q_CLASSINFO(QT_STRINGIFY(__nut_NAME_PERFIX __nut_TABLE " " #type), #name) \ + NUT_INFO(__nut_TABLE, type, name) \ Q_PROPERTY(type* name READ name) \ Q_PROPERTY(NUT_WRAP_NAMESPACE(TableSet) name##s READ name##s) \ type* m_##name; \ @@ -54,7 +54,7 @@ public: \ //Table #define NUT_DECLARE_FIELD(type, name, read, write) \ Q_PROPERTY(type name READ read WRITE write) \ - Q_CLASSINFO(QT_STRINGIFY(__nut_NAME_PERFIX #name " " __nut_FIELD), #name) \ + NUT_INFO(__nut_FIELD, name, 0) \ type m_##name; \ public: \ static NUT_WRAP_NAMESPACE(FieldPhrase) name ## Field(){ \ @@ -72,7 +72,7 @@ public: \ #define NUT_FOREGION_KEY(type, keytype, name, read, write) \ Q_PROPERTY(type* name READ read WRITE write) \ NUT_DECLARE_FIELD(keytype, name##Id, read##Id, write##Id) \ - Q_CLASSINFO(QT_STRINGIFY(__nut_NAME_PERFIX #name "Id " __nut_FOREGION_KEY), #type) \ + NUT_INFO(__nut_FOREGION_KEY, name, type) \ type *m_##name; \ public: \ type *read() const { return m_##name ; } \ @@ -97,14 +97,14 @@ public: \ } -#define NUT_PRIMARY_KEY(x) Q_CLASSINFO(QT_STRINGIFY(__nut_NAME_PERFIX #x " " __nut_PRIMARY_KEY), #x) -#define NUT_AUTO_INCREMENT(x) Q_CLASSINFO(QT_STRINGIFY(__nut_NAME_PERFIX #x " " __nut_AUTO_INCREMENT), #x) +#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_PRIMARY_AUTO_INCREMENT(x) NUT_PRIMARY_KEY(x) \ NUT_AUTO_INCREMENT(x) -#define NUT_UNIQUE(x) Q_CLASSINFO(QT_STRINGIFY(__nut_NAME_PERFIX #x " " __nut_UNIQUE), #x) -#define NUT_LEN(field, len) Q_CLASSINFO(QT_STRINGIFY(__nut_NAME_PERFIX #field " " __nut_LEN), #len) -#define NUT_DEFAULT_VALUE(x, n) Q_CLASSINFO(QT_STRINGIFY(__nut_NAME_PERFIX #x " " __nut_DEFAULT_VALUE), #n) -#define NUT_NOT_NULL(x) Q_CLASSINFO(QT_STRINGIFY(__nut_NAME_PERFIX #x " " __nut_NOT_NULL), "1") +#define NUT_UNIQUE(x) NUT_INFO(__nut_UNIQUE, x, 0) +#define NUT_LEN(field, len) NUT_INFO(__nut_LEN, field, len) +#define NUT_DEFAULT_VALUE(x, n) NUT_INFO(__nut_DEFAULT_VALUE, x, n) +#define NUT_NOT_NULL(x) NUT_INFO(__nut_NOT_NULL, x, 1) #define NUT_INDEX(name, field, order) #endif // SYNTAX_DEFINES_H diff --git a/src/generators/sqlgeneratorbase.cpp b/src/generators/sqlgeneratorbase.cpp index 06029a2..c99c162 100644 --- a/src/generators/sqlgeneratorbase.cpp +++ b/src/generators/sqlgeneratorbase.cpp @@ -377,22 +377,12 @@ QString SqlGeneratorBase::deleteRecords(QString tableName, QString where) return sql; } -QString SqlGeneratorBase::selectCommand(SqlGeneratorBase::AgregateType t, - QString agregateArg, - QList &wheres, - QList &orders, - QStringList joins, int skip, int take) -{ - return selectCommand(t, agregateArg, wheres, orders, joins, skip, take); -} - QString SqlGeneratorBase::selectCommand(SqlGeneratorBase::AgregateType t, QString agregateArg, QList &wheres, QList &orders, QStringList joins, - int skip, int take, - QStringList *order) + int skip, int take) { Q_UNUSED(take); Q_UNUSED(skip); @@ -402,8 +392,6 @@ QString SqlGeneratorBase::selectCommand(SqlGeneratorBase::AgregateType t, QString from = join(joins, &joinedOrders); QString where = createWhere(wheres); QString orderText = joinedOrders.join(", "); - if (order != Q_NULLPTR) - order = joinedOrders; foreach (WherePhrase p, orders) { if (orderText != "") diff --git a/src/generators/sqlgeneratorbase_p.h b/src/generators/sqlgeneratorbase_p.h index 5668116..d729899 100644 --- a/src/generators/sqlgeneratorbase_p.h +++ b/src/generators/sqlgeneratorbase_p.h @@ -83,13 +83,6 @@ public: QList &orders, QStringList joins, int skip = -1, int take = -1); - virtual QString selectCommand(AgregateType t, - QString agregateArg, - QList &wheres, - QList &orders, - QStringList joins, - int skip = -1, int take = -1, - QStringList *order = Q_NULLPTR); virtual QString deleteCommand(QList &wheres, QString tableName); diff --git a/src/query.h b/src/query.h index 51150e1..325696c 100644 --- a/src/query.h +++ b/src/query.h @@ -104,6 +104,7 @@ Q_OUTOFLINE_TEMPLATE Query::Query(Database *database, TableSetBase *tableSet, d->database = database; d->tableSet = tableSet; + d->className = T::staticMetaObject.className(); d->tableName = // TableModel::findByClassName(T::staticMetaObject.className())->name(); d->database->model() @@ -125,22 +126,76 @@ Q_OUTOFLINE_TEMPLATE QList Query::toList(int count) QList result; d->select = "*"; - d->joins.prepend(d->tableName); + d->joins.prepend(d->className); + + qDebug() << "JOINS="<< d->joins; - qDebug() << "JOINS="<< d->database->sqlGenertor()->join(d->joins); - // QSqlQuery q = - // d->database->exec(d->database->sqlGenertor()->selectCommand(d->wheres, - // d->orders, d->tableName, d->joinClassName)); - QStringList orders; d->sql = d->database->sqlGenertor()->selectCommand( SqlGeneratorBase::SelectAll, "", d->wheres, d->orderPhrases, - d->joins, d->skip, d->take, &orders); + d->joins, d->skip, d->take); QSqlQuery q = d->database->exec(d->sql); - while (q.next()) { - + struct LevelData{ + QString key; + QString className; + QVariant keyValue; + int typeId; + TableSetBase *tableSet; + Table *lastRow; + }; + QVector levels; + foreach (QString className, d->joins) { + LevelData data; + data.className = className; + TableModel *m = d->database->model().tableByClassName(className); + if (!m) + qFatal("Model '%s' not found!!!", qPrintable(className)); + data.key = m->primaryKey(); + data.typeId = m->typeId(); + data.keyValue = QVariant(); + data.tableSet = 0; + levels.append(data); } + QList returnList; + while (q.next()) { + for (int i = 0; i < levels.count(); i++) { + LevelData &data = levels[i]; + if (!data.tableSet || data.keyValue != q.value(data.key)) { + + //create table row + Table *childTable; + if (data.className == d->className) { + childTable = new T(); + returnList.append(dynamic_cast(childTable)); + } else { + const QMetaObject *childMetaObject + = QMetaType::metaObjectForType(data.typeId); + childTable = qobject_cast(childMetaObject->newInstance()); + } + + QStringList childFields + = d->database->model().tableByClassName(data.className)->fieldsNames(); + foreach (QString field, childFields) + childTable->setProperty(field.toLatin1().data(), q.value(field)); + + //set last created row + data.lastRow = childTable; + if (i < levels.count() - 1) { + QSet tableSets = childTable->tableSets; + foreach (TableSetBase *ts, tableSets) + if (ts->childClassName() == levels[i + 1].className) + data.tableSet = ts; + } + if (i) + childTable->setTableSet(levels[i - 1].tableSet); + } + } + } + if (m_autoDelete) + deleteLater(); + return returnList; +/* QString pk = d->database->model().tableByName(d->tableName)->primaryKey(); QVariant lastPkValue = QVariant(); int childTypeId = 0; @@ -173,15 +228,6 @@ Q_OUTOFLINE_TEMPLATE QList Query::toList(int count) T *t = new T(); foreach (QString field, masterFields) t->setProperty(field.toLatin1().data(), q.value(field)); - // for (int i = 0; i < t->metaObject()->propertyCount(); - // i++) { - // const QMetaProperty p = - // t->metaObject()->property(i); - - // p.write(t, - // d->database->sqlGenertor()->readValue(p.type(), - // q.value(p.name()))); - // } t->setTableSet(d->tableSet); t->setStatus(Table::FeatchedFromDB); @@ -226,6 +272,7 @@ Q_OUTOFLINE_TEMPLATE QList Query::toList(int count) if (m_autoDelete) deleteLater(); return result; + */ } template diff --git a/src/query_p.h b/src/query_p.h index 250a0f6..a768ef3 100644 --- a/src/query_p.h +++ b/src/query_p.h @@ -41,6 +41,7 @@ public: ~QueryPrivate(); QString sql; + QString className; QString tableName; QString select; Database *database; diff --git a/src/table.cpp b/src/table.cpp index 47af793..c310e64 100644 --- a/src/table.cpp +++ b/src/table.cpp @@ -22,6 +22,7 @@ #include #include "table.h" #include "database.h" +#include "databasemodel.h" #include "generators/sqlgeneratorbase_p.h" NUT_BEGIN_NAMESPACE @@ -130,6 +131,7 @@ int Table::save(Database *db) { QSqlQuery q = db->exec(db->sqlGenertor()->saveRecord(this, db->tableName(metaObject()->className()))); + if(status() == Added && isPrimaryKeyAutoIncrement()) setProperty(primaryKey().toLatin1().data(), q.lastInsertId()); diff --git a/src/tablemodel.cpp b/src/tablemodel.cpp index 5696ff6..bcded9c 100644 --- a/src/tablemodel.cpp +++ b/src/tablemodel.cpp @@ -144,6 +144,23 @@ bool TableModel::operator !=(const TableModel &t) const return !(*this == t); } +bool TableModel::checkClassInfo(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]; + qDebug() << Q_FUNC_INFO << parts; + return true; + } +} + TableModel::TableModel(int typeId, QString tableName) { //TODO: check that @@ -163,20 +180,19 @@ TableModel::TableModel(int typeId, QString tableName) // get fields names for(int j = 0; j < tableMetaObject->classInfoCount(); j++){ - QString name = tableMetaObject->classInfo(j).name(); - name = name.replace("\"", ""); + QString type; + QString name; + QString value; - name = name.remove(__nut_NAME_PERFIX); + if (!checkClassInfo(tableMetaObject->classInfo(j), + type, name, value)) { + continue; + } - if(name.contains(" ")){ - QStringList parts = name.split(" "); - QString propName = parts.at(1); - - if(propName == __nut_FIELD){ - FieldModel *f = new FieldModel; - f->name = parts.at(0); - _fields.append(f); - } + if(type == __nut_FIELD){ + FieldModel *f = new FieldModel; + f->name = name; + _fields.append(f); } } // Browse all fields @@ -195,48 +211,46 @@ TableModel::TableModel(int typeId, QString tableName) // Browse class infos for(int j = 0; j < tableMetaObject->classInfoCount(); j++){ - QString name = tableMetaObject->classInfo(j).name(); - QString value = tableMetaObject->classInfo(j).value(); + QString type; + QString name; + QString value; - name = name.replace("\"", "").remove(__nut_NAME_PERFIX); - value = value.replace("\"", ""); + if (!checkClassInfo(tableMetaObject->classInfo(j), + type, name, value)) { + continue; + } - if(name.contains(" ")){ - QStringList parts = name.split(" "); - QString propName = parts.at(1); + if(type == __nut_FOREGION_KEY){ + RelationModel *fk = new RelationModel; + fk->localColumn = name; + fk->foregionColumn = value; + fk->className = value; + _foregionKeys.append(fk); + } - if(propName == __nut_FOREGION_KEY){ - RelationModel *fk = new RelationModel; - fk->localColumn = parts.at(0); - fk->foregionColumn = value; - fk->className = value; - _foregionKeys.append(fk); - qDebug() << "REL="<length = value.toInt(); - else if(propName == __nut_NOT_NULL) - f->notNull = true; - else if(propName == __nut_DEFAULT_VALUE) - f->defaultValue = value; - else if(propName == __nut_PRIMARY_KEY) - f->isPrimaryKey = true; - else if(propName == __nut_AUTO_INCREMENT) - f->isAutoIncrement = true; - else if(propName == __nut_UNIQUE) - f->isUnique = true; + if(type == __nut_FIELD){ } + + + FieldModel *f = field(name); + if(!f) + continue; + + if(type == __nut_LEN) + f->length = value.toInt(); + else if(type == __nut_NOT_NULL) + f->notNull = true; + else if(type == __nut_DEFAULT_VALUE) + f->defaultValue = value; + else if(type == __nut_PRIMARY_KEY) + f->isPrimaryKey = true; + else if(type == __nut_AUTO_INCREMENT) + f->isAutoIncrement = true; + else if(type == __nut_UNIQUE) + f->isUnique = true; + + } if(!findByTypeId(typeId) && !tableName.isNull()) diff --git a/src/tablemodel.h b/src/tablemodel.h index 2d58d2c..fd0d704 100644 --- a/src/tablemodel.h +++ b/src/tablemodel.h @@ -117,6 +117,7 @@ private: QList _fields; QList _foregionKeys; static QSet_allModels; + bool checkClassInfo(const QMetaClassInfo &classInfo, QString type, QString name, QString value); }; NUT_END_NAMESPACE diff --git a/test/basic/maintest.h b/test/basic/maintest.h index 06e3ee1..1ba679a 100644 --- a/test/basic/maintest.h +++ b/test/basic/maintest.h @@ -13,7 +13,7 @@ class MainTest : public QObject WeblogDatabase db; int postId; Post *post; - User *User; + User *user; public: explicit MainTest(QObject *parent = 0);