From f3748241ff5c4b96d82ed319bb86b8d5fa00d421 Mon Sep 17 00:00:00 2001 From: Hamed Masafi Date: Sat, 16 Feb 2019 17:06:38 +0330 Subject: [PATCH] upgrade passed by sqlite [skip ci] --- src/changelogtable.h | 2 +- src/database.cpp | 34 ++++++------ src/database.h | 2 +- src/database_p.h | 2 + src/databasemodel.cpp | 12 ++--- src/databasemodel.h | 6 +-- src/generators/postgresqlgenerator.cpp | 4 -- src/generators/sqlgeneratorbase.cpp | 47 +++++++++-------- src/generators/sqlgeneratorbase_p.h | 6 +-- src/generators/sqlitegenerator.cpp | 73 ++++++++++++++++++++++++++ src/generators/sqlitegenerator.h | 7 +-- src/generators/sqlservergenerator.cpp | 2 +- src/phrase.cpp | 4 -- src/table.cpp | 6 ++- test/tst_join/jointest.cpp | 10 ++-- test/tst_quuid/tst_uuid.cpp | 4 +- test/tst_upgrades/table3.h | 2 + test/tst_upgrades/tst_upgrades.cpp | 11 ++++ test/tst_upgrades/tst_upgrades.h | 1 + 19 files changed, 160 insertions(+), 75 deletions(-) diff --git a/src/changelogtable.h b/src/changelogtable.h index 84475a5..4d580de 100644 --- a/src/changelogtable.h +++ b/src/changelogtable.h @@ -35,7 +35,7 @@ class ChangeLogTable : public Table NUT_DECLARE_FIELD(QString, data, data, setData) - NUT_DECLARE_FIELD(QString, version, version, setVersion) + NUT_DECLARE_FIELD(int, version, version, setVersion) public: explicit ChangeLogTable(QObject *parentTableSet = Q_NULLPTR); diff --git a/src/database.cpp b/src/database.cpp index f462692..ced3d38 100644 --- a/src/database.cpp +++ b/src/database.cpp @@ -173,16 +173,6 @@ bool DatabasePrivate::updateDatabase() if (db.lastError().type() == QSqlError::NoError) { q->databaseUpdated(last.version(), current.version()); - - //TODO: remove this - for (int i = 0; i < q->metaObject()->methodCount(); i++) { - QMetaMethod m = q->metaObject()->method(i); - if (m.name() == "update" + current.version()) { - m.invoke(q, Qt::DirectConnection, - Q_ARG(QString, current.version())); - break; - } - } } else { qWarning("Unable update database, error = %s", db.lastError().text().toLatin1().data()); @@ -220,7 +210,9 @@ bool DatabasePrivate::getCurrectScheema() if (!nutClassInfoString(q->metaObject()->classInfo(i), type, name, value)) { - qDebug() << "No valid table in" << q->metaObject()->classInfo(i).value(); + + errorMessage = QString("No valid table in %1") + .arg(q->metaObject()->classInfo(i).value()); continue; } if (type == __nut_TABLE) { @@ -232,13 +224,17 @@ bool DatabasePrivate::getCurrectScheema() if (!typeId) qFatal("The class %s is not registered with qt meta object", qPrintable(name)); -qDebug() << "Table found" << typeId; + TableModel *sch = new TableModel(typeId, value); currentModel.append(sch); } - if (type == __nut_DB_VERSION) - currentModel.setVersion(name); + if (type == __nut_DB_VERSION) { + bool ok; + int version = value.toInt(&ok); + if (!ok) + qFatal("NUT_DB_VERSION macro accept version in format 'x'"); + currentModel.setVersion(version); /* TODO: remove QStringList version @@ -254,6 +250,7 @@ qDebug() << "Table found" << typeId; if (!ok) qFatal("NUT_DB_VERSION macro accept version in format 'x' or " "'x[.y]' only, and x,y must be integer values\n");*/ + } } for (int i = 1; i < q->metaObject()->propertyCount(); i++) { @@ -337,7 +334,7 @@ bool DatabasePrivate::putModelToDatabase() /*current.remove(__CHANGE_LOG_TABLE_NAME)*/; auto *changeLog = new ChangeLogTable(); - changeLog->setData(QJsonDocument(current.toJson()).toJson()); + changeLog->setData(QJsonDocument(current.toJson()).toJson(QJsonDocument::Compact)); changeLog->setVersion(current.version()); changeLogs->append(changeLog); q->saveChanges(); @@ -359,9 +356,10 @@ bool DatabasePrivate::putModelToDatabase() void DatabasePrivate::createChangeLogs() { // currentModel.model("change_log") - QString diff = sqlGenertor->diff(nullptr, currentModel.tableByName("__change_log")); + QStringList diff = sqlGenertor->diff(nullptr, currentModel.tableByName("__change_log")); - db.exec(diff); + foreach (QString s, diff) + db.exec(s); } /*! @@ -530,7 +528,7 @@ QSqlDatabase Database::database() return d->db; } -void Database::databaseUpdated(QString oldVersion, QString newVersion) +void Database::databaseUpdated(int oldVersion, int newVersion) { Q_UNUSED(oldVersion); Q_UNUSED(newVersion); diff --git a/src/database.h b/src/database.h index 56692d3..bfeab75 100644 --- a/src/database.h +++ b/src/database.h @@ -73,7 +73,7 @@ public: protected: //remove minor version - virtual void databaseUpdated(QString oldVersion, QString newVersion); + virtual void databaseUpdated(int oldVersion, int newVersion); public slots: void setDatabaseName(QString databaseName); diff --git a/src/database_p.h b/src/database_p.h index cbe2379..46ae47c 100644 --- a/src/database_p.h +++ b/src/database_p.h @@ -70,6 +70,8 @@ public: QSet tableSets; bool isDatabaseNew; + + QString errorMessage; }; NUT_END_NAMESPACE diff --git a/src/databasemodel.cpp b/src/databasemodel.cpp index 084d186..45e0e25 100644 --- a/src/databasemodel.cpp +++ b/src/databasemodel.cpp @@ -31,13 +31,13 @@ QMap DatabaseModel::_models; #define NODE_VERSION "version" #define NODE_TABLES "tables" DatabaseModel::DatabaseModel(const QString &name) : - QList(), _databaseClassName(name), _version(QString()) + QList(), _databaseClassName(name), _version(0) { _models.insert(name, this); } DatabaseModel::DatabaseModel(const DatabaseModel &other) : - QList(other), _version(QString()) + QList(other), _version(0) { } @@ -45,7 +45,7 @@ DatabaseModel::DatabaseModel(const DatabaseModel &other) : DatabaseModel::DatabaseModel(const QJsonObject &json) : QList() { - setVersion(json.value(NODE_VERSION).toString()); + setVersion(json.value(NODE_VERSION).toInt()); QJsonObject tables = json.value(NODE_TABLES).toObject(); foreach (QString key, tables.keys()) { @@ -171,7 +171,7 @@ DatabaseModel DatabaseModel::fromJson(QJsonObject &json) { DatabaseModel model; - model.setVersion(json.value(NODE_VERSION).toString()); + model.setVersion(json.value(NODE_VERSION).toInt()); QJsonObject tables = json.value(NODE_TABLES).toObject(); foreach (QString key, tables.keys()) { @@ -184,12 +184,12 @@ DatabaseModel DatabaseModel::fromJson(QJsonObject &json) return model; } -QString DatabaseModel::version() const +int DatabaseModel::version() const { return _version; } -void DatabaseModel::setVersion(QString version) +void DatabaseModel::setVersion(int version) { _version = version; } diff --git a/src/databasemodel.h b/src/databasemodel.h index 9abab8e..4e12408 100644 --- a/src/databasemodel.h +++ b/src/databasemodel.h @@ -36,7 +36,7 @@ struct RelationModel; class DatabaseModel : public QList { QString _databaseClassName; - QString _version; + int _version; static QMap _models; public: @@ -61,8 +61,8 @@ public: QJsonObject toJson() const; operator QJsonObject(); - QString version() const; - void setVersion(QString version); + int version() const; + void setVersion(int version); bool remove(const QString &tableName); diff --git a/src/generators/postgresqlgenerator.cpp b/src/generators/postgresqlgenerator.cpp index d27b11b..c6b153c 100644 --- a/src/generators/postgresqlgenerator.cpp +++ b/src/generators/postgresqlgenerator.cpp @@ -171,13 +171,9 @@ QString PostgreSqlGenerator::fieldType(FieldModel *field) return "TEXT"; default: - qDebug() << "Type for " << (int)field->type << field->type << "(" << QMetaType::typeName(field->type) << ")" << "nut supported"; dbType = QString(); } - if(field->type == (unsigned)QMetaType::type("Nut::DbGeography")) - dbType = "GEOGRAPHY"; - return dbType; } diff --git a/src/generators/sqlgeneratorbase.cpp b/src/generators/sqlgeneratorbase.cpp index 90b0923..dfe1ee9 100644 --- a/src/generators/sqlgeneratorbase.cpp +++ b/src/generators/sqlgeneratorbase.cpp @@ -132,7 +132,7 @@ QStringList SqlGeneratorBase::diff(const DatabaseModel &lastModel, foreach (TableModel *table, unionModel) { TableModel *oldTable = lastModel.tableByName(table->name()); TableModel *newTable = newModel.tableByName(table->name()); - QString sql = diff(oldTable, newTable); + QStringList sql = diff(oldTable, newTable); if (!sql.isEmpty()) ret << sql; // QString sqlRel = diffRelation(oldTable, newTable); @@ -148,7 +148,7 @@ QString SqlGeneratorBase::diff(FieldModel *oldField, FieldModel *newField) QString sql = QString(); if (oldField && newField) if (*oldField == *newField) - return QString(); + return sql; if (!newField) { sql = "DROP COLUMN " + oldField->name; @@ -162,14 +162,14 @@ QString SqlGeneratorBase::diff(FieldModel *oldField, FieldModel *newField) return sql; } -QString SqlGeneratorBase::diff(TableModel *oldTable, TableModel *newTable) +QStringList SqlGeneratorBase::diff(TableModel *oldTable, TableModel *newTable) { if (oldTable && newTable) if (*oldTable == *newTable) - return QString(); + return QStringList(); if (!newTable) - return "DROP TABLE " + oldTable->name(); + return QStringList() << ("DROP TABLE " + oldTable->name()); QList fieldNames; QList relations; @@ -197,12 +197,12 @@ QString SqlGeneratorBase::diff(TableModel *oldTable, TableModel *newTable) FieldModel *oldField = oldTable->field(fieldName); QString buffer = diff(oldField, newField); - if (!buffer.isNull()) + if (!buffer.isEmpty()) columnSql << buffer; } else { QString declare = fieldDeclare(newField); if (declare.isEmpty()) - return declare; + return QStringList() << declare; columnSql << declare; } } @@ -231,14 +231,16 @@ QString SqlGeneratorBase::diff(TableModel *oldTable, TableModel *newTable) sql = QString("CREATE TABLE %1 \n(%2)") .arg(newTable->name(), columnSql.join(",\n")); + } - return sql; + return QStringList() << sql; } -QString SqlGeneratorBase::diffRelation(TableModel *oldTable, TableModel *newTable) +QStringList SqlGeneratorBase::diffRelation(TableModel *oldTable, TableModel *newTable) { + QStringList ret; if (!newTable) - return QString(); + return ret; QList relations; @@ -258,20 +260,21 @@ QString SqlGeneratorBase::diffRelation(TableModel *oldTable, TableModel *newTabl if (oldTable) oldRelation = oldTable->foregionKeyByField(fieldName); - QString buffer = diff(oldRelation, newRelation); - if (!buffer.isNull()) - columnSql << buffer; + QStringList buffer = diff(oldRelation, newRelation); + if (!buffer.isEmpty()) + columnSql << buffer.at(0); } if (columnSql.count()) - return "ALTER TABLE " + newTable->name() + "\n" - + columnSql.join(",\n"); + ret.append("ALTER TABLE " + newTable->name() + "\n" + + columnSql.join(",\n")); - return QString(); + return ret; } -QString SqlGeneratorBase::diff(RelationModel *oldRel, RelationModel *newRel) +QStringList SqlGeneratorBase::diff(RelationModel *oldRel, RelationModel *newRel) { + QStringList ret; /* CONSTRAINT FK_PersonOrder FOREIGN KEY (PersonID) REFERENCES Persons(PersonID) @@ -285,19 +288,19 @@ QString SqlGeneratorBase::diff(RelationModel *oldRel, RelationModel *newRel) .arg(newRelation->foreignColumn); */ if (!oldRel) - return QString("ADD CONSTRAINT FK_%1 FOREIGN KEY (%1) " + ret.append(QString("ADD CONSTRAINT FK_%1 FOREIGN KEY (%1) " "REFERENCES %2(%3)") .arg(newRel->localColumn, newRel->masterTable->name(), - newRel->foreignColumn); + newRel->foreignColumn)); if (!newRel) - return QString("ADD CONSTRAINT FK_%1 FOREIGN KEY (%1) " + ret.append(QString("ADD CONSTRAINT FK_%1 FOREIGN KEY (%1) " "REFERENCES %2(%3)") .arg(oldRel->localColumn, oldRel->masterTable->name(), - oldRel->foreignColumn); + oldRel->foreignColumn)); // if (*oldRel == *newRel) - return QString(); + return ret; } QString SqlGeneratorBase::join(const QString &mainTable, diff --git a/src/generators/sqlgeneratorbase_p.h b/src/generators/sqlgeneratorbase_p.h index eab48a0..ff6a8c4 100644 --- a/src/generators/sqlgeneratorbase_p.h +++ b/src/generators/sqlgeneratorbase_p.h @@ -84,9 +84,9 @@ public: virtual QStringList diff(const DatabaseModel &lastModel, const DatabaseModel &newModel); virtual QString diff(FieldModel *oldField, FieldModel *newField); - virtual QString diff(TableModel *oldTable, TableModel *newTable); - virtual QString diffRelation(TableModel *oldTable, TableModel *newTable); - virtual QString diff(RelationModel *oldRel, RelationModel *newRel); + virtual QStringList diff(TableModel *oldTable, TableModel *newTable); + virtual QStringList diffRelation(TableModel *oldTable, TableModel *newTable); + virtual QStringList diff(RelationModel *oldRel, RelationModel *newRel); virtual QString join(const QString &mainTable, const QList &list, diff --git a/src/generators/sqlitegenerator.cpp b/src/generators/sqlitegenerator.cpp index 05b33d0..29de452 100644 --- a/src/generators/sqlitegenerator.cpp +++ b/src/generators/sqlitegenerator.cpp @@ -95,6 +95,79 @@ QString SqliteGenerator::fieldType(FieldModel *field) } } + +QStringList SqliteGenerator::diff(TableModel *oldTable, TableModel *newTable) +{ + QStringList ret; + + if (oldTable && newTable) + if (*oldTable == *newTable) + return ret; + + QStringList newTableSql = SqlGeneratorBase::diff(nullptr, newTable); + + if (!newTable) + return QStringList() << "DROP TABLE " + oldTable->name(); + + if (!oldTable) + return newTableSql; + + QList fieldNames; + QList relations; + + foreach (FieldModel *f, oldTable->fields()) + if (!fieldNames.contains(f->name)) + fieldNames.append(f->name); + foreach (RelationModel *r, oldTable->foregionKeys()) + if (!relations.contains(r->localColumn)) + relations.append(r->localColumn); + + foreach (FieldModel *f, newTable->fields()) + if (!fieldNames.contains(f->name)) + fieldNames.append(f->name); + foreach (RelationModel *r, newTable->foregionKeys()) + if (!relations.contains(r->localColumn)) + relations.append(r->localColumn); + + QString columns; + foreach (FieldModel *f, oldTable->fields()) { + if (!newTable->field(f->name)) + continue; + + if (!columns.isEmpty()) + columns.append(", "); + columns.append(f->name); + } + + /* + ALTER TABLE sampleTable RENAME TO sqlitestudio_temp_table; + + CREATE TABLE sampleTable ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + t BIGINT, + m CHAR + ); + + INSERT INTO sampleTable ( + id, + t, + m + ) + SELECT id, + t, + m + FROM sqlitestudio_temp_table; + + DROP TABLE sqlitestudio_temp_table; + */ + + ret.append("ALTER TABLE " + newTable->name() + " RENAME TO sqlitestudio_temp_table;"); + ret.append(newTableSql); + ret.append(QString("INSERT INTO %1 ( %2 ) SELECT %2 FROM sqlitestudio_temp_table;") + .arg(newTable->name(), columns)); + ret.append("DROP TABLE sqlitestudio_temp_table;"); + return ret; +} void SqliteGenerator::appendSkipTake(QString &sql, int skip, int take) { if (take != -1 && skip != -1) diff --git a/src/generators/sqlitegenerator.h b/src/generators/sqlitegenerator.h index 2769d58..d796880 100644 --- a/src/generators/sqlitegenerator.h +++ b/src/generators/sqlitegenerator.h @@ -31,11 +31,12 @@ class SqliteGenerator : public SqlGeneratorBase public: explicit SqliteGenerator(Database *parent = nullptr); - QString fieldType(FieldModel *field); + QString fieldType(FieldModel *field) override; - void appendSkipTake(QString &sql, int skip, int take); + void appendSkipTake(QString &sql, int skip, int take) override; - QString primaryKeyConstraint(const TableModel *table) const; + QString primaryKeyConstraint(const TableModel *table) const override; + QStringList diff(TableModel *oldTable, TableModel *newTable) override; }; NUT_END_NAMESPACE diff --git a/src/generators/sqlservergenerator.cpp b/src/generators/sqlservergenerator.cpp index 989755e..fc8481b 100644 --- a/src/generators/sqlservergenerator.cpp +++ b/src/generators/sqlservergenerator.cpp @@ -146,7 +146,7 @@ QString SqlServerGenerator::diff(FieldModel *oldField, FieldModel *newField) QString sql = QString(); if (oldField && newField) if (*oldField == *newField) - return QString(); + return sql; if (!newField) { sql = "DROP COLUMN " + oldField->name; diff --git a/src/phrase.cpp b/src/phrase.cpp index 61d71d9..7b36e27 100644 --- a/src/phrase.cpp +++ b/src/phrase.cpp @@ -97,14 +97,12 @@ AbstractFieldPhrase::AbstractFieldPhrase(const char *className, const char *fieldName) :data(new PhraseData(className, fieldName)) { - qDebug() <<"AbstractFieldPhrase created"<parents++; - qDebug() <<"Copy ctor"<toString()<parents; } AbstractFieldPhrase::AbstractFieldPhrase(AbstractFieldPhrase &&other) @@ -358,7 +356,6 @@ ConditionalPhrase::ConditionalPhrase() : data(nullptr) ConditionalPhrase::ConditionalPhrase(const ConditionalPhrase &other) { - qDebug() << "************* ctor called:"; data = other.data; data->parents++; // const_cast(other).data = 0; @@ -367,7 +364,6 @@ ConditionalPhrase::ConditionalPhrase(const ConditionalPhrase &other) #ifdef Q_COMPILER_RVALUE_REFS ConditionalPhrase::ConditionalPhrase(const ConditionalPhrase &&other) { - qDebug() << "************* ctor called:"; this->data = qMove(other.data); } #endif diff --git a/src/table.cpp b/src/table.cpp index f841ced..23768ac 100644 --- a/src/table.cpp +++ b/src/table.cpp @@ -39,9 +39,11 @@ NUT_BEGIN_NAMESPACE * This should be fixed to v1.2 */ -Table::Table(QObject *parent) : QObject(parent), myModel(nullptr), +Table::Table(QObject *parent) : QObject(parent), _status(NewCreated), _parentTableSet(nullptr) -{ } +{ + myModel = TableModel::findByClassName(metaObject()->className()); +} void Table::add(TableSetBase *t) { diff --git a/test/tst_join/jointest.cpp b/test/tst_join/jointest.cpp index 05918cb..87c2530 100644 --- a/test/tst_join/jointest.cpp +++ b/test/tst_join/jointest.cpp @@ -22,11 +22,11 @@ JoinTest::JoinTest(QObject *parent) : QObject(parent) void JoinTest::initTestCase() { - qDebug() << "User type id:" << qRegisterMetaType(); - qDebug() << "Post type id:" << qRegisterMetaType(); - qDebug() << "Comment type id:" << qRegisterMetaType(); - qDebug() << "Score type id:" << qRegisterMetaType(); - qDebug() << "DB type id:" << qRegisterMetaType(); + REGISTER(User); + REGISTER(Post); + REGISTER(Comment); + REGISTER(Score); + REGISTER(WeblogDatabase); db.setDriver(DRIVER); db.setHostName(HOST); diff --git a/test/tst_quuid/tst_uuid.cpp b/test/tst_quuid/tst_uuid.cpp index 03f127d..e1d6d72 100644 --- a/test/tst_quuid/tst_uuid.cpp +++ b/test/tst_quuid/tst_uuid.cpp @@ -19,8 +19,8 @@ UuidTest::UuidTest(QObject *parent) : QObject(parent) void UuidTest::initTestCase() { - qDebug() << "Test type id:" << qRegisterMetaType(); - qDebug() << "DB type id:" << qRegisterMetaType(); + REGISTER(Test); + REGISTER(TestDatabase); QFile::remove(DATABASE); diff --git a/test/tst_upgrades/table3.h b/test/tst_upgrades/table3.h index 0b68424..b0c3458 100644 --- a/test/tst_upgrades/table3.h +++ b/test/tst_upgrades/table3.h @@ -10,6 +10,8 @@ class Table3 : public Nut::Table NUT_PRIMARY_AUTO_INCREMENT(id) NUT_DECLARE_FIELD(int, id, id, setId) + NUT_DECLARE_FIELD(QString, grade, grade, setGrade) + public: Q_INVOKABLE Table3(QObject *parent = Q_NULLPTR); diff --git a/test/tst_upgrades/tst_upgrades.cpp b/test/tst_upgrades/tst_upgrades.cpp index 8d4cf68..959a935 100644 --- a/test/tst_upgrades/tst_upgrades.cpp +++ b/test/tst_upgrades/tst_upgrades.cpp @@ -7,6 +7,7 @@ #include "table1.h" #include "table2.h" #include "table3.h" +#include "query.h" #include "tst_upgrades.h" #include "consts.h" @@ -55,6 +56,12 @@ void Upgrades::version2() DB2 db; initDb(db); QTEST_ASSERT(db.open()); + + Table2 t; + t.setStr("0"); + db.sampleTable()->append(&t); + db.saveChanges(); + id = t.id(); } void Upgrades::version3() @@ -62,6 +69,10 @@ void Upgrades::version3() DB3 db; initDb(db); QTEST_ASSERT(db.open()); + + auto t = db.sampleTable()->query() + ->first(); + QTEST_ASSERT(id == t->id()); } diff --git a/test/tst_upgrades/tst_upgrades.h b/test/tst_upgrades/tst_upgrades.h index fcdfbca..7556eb4 100644 --- a/test/tst_upgrades/tst_upgrades.h +++ b/test/tst_upgrades/tst_upgrades.h @@ -12,6 +12,7 @@ class Upgrades : public QObject void initDb(Nut::Database &db); + int id; public: Upgrades(); ~Upgrades();