diff --git a/.travis.yml b/.travis.yml index 528bb2a..dc854ff 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,9 +1,79 @@ +#Based on https://github.com/pcolby/libqtaws/blob/master/.travis.yml +language: cpp + +os: + - linux + - osx + +dist: trusty + +compiler: + - clang + - gcc + +env: + matrix: + - QT=5 BREW= + - QT=5 BREW=ex PPA=ubuntu-sdk-team/ppa + - QT=51 BREW=ex PPA=beineri/opt-qt511-trusty + - QT=52 BREW=ex PPA=beineri/opt-qt521-trusty + - QT=53 BREW=ex PPA=beineri/opt-qt532-trusty + - QT=54 BREW=ex PPA=beineri/opt-qt542-trusty + - QT=55 BREW=@5.5 PPA=beineri/opt-qt551-trusty + - QT=56 BREW=ex PPA=beineri/opt-qt562-trusty + - QT=56 BREW=ex PPA=beineri/opt-qt563-trusty + - QT=57 BREW=@5.7 PPA=beineri/opt-qt571-trusty + - QT=58 BREW=ex PPA=beineri/opt-qt58-trusty + - QT=59 BREW=@5.9 PPA=beineri/opt-qt591-trusty + +matrix: + exclude: + - { os: osx, env: QT=5 BREW=ex PPA=ubuntu-sdk-team/ppa } + - { os: osx, env: QT=51 BREW=ex PPA=beineri/opt-qt511-trusty } + - { os: osx, env: QT=52 BREW=ex PPA=beineri/opt-qt521-trusty } + - { os: osx, env: QT=53 BREW=ex PPA=beineri/opt-qt532-trusty } + - { os: osx, env: QT=54 BREW=ex PPA=beineri/opt-qt542-trusty } + - { os: osx, env: QT=56 BREW=ex PPA=beineri/opt-qt562-trusty } + - { os: osx, env: QT=56 BREW=ex PPA=beineri/opt-qt563-trusty } + - { os: osx, env: QT=58 BREW=ex PPA=beineri/opt-qt58-trusty } + +addons: + coverity_scan: + project: + name: "HamedMasafi/Nut" + description: "Build submitted via Travis CI" + # notification_email: em@h + build_command_prepend: > + cp -a "$TRAVIS_BUILD_DIR" "$TRAVIS_BUILD_DIR-scan" && + pushd "$TRAVIS_BUILD_DIR-scan" && + qmake -qt=qt5 -Wall -Wlogic -Wparser CONFIG+=debug_and_release + build_command: make all + #branch_pattern: coverity + before_install: - - sudo add-apt-repository --yes ppa:ubuntu-sdk-team/ppa - - sudo apt-get update -qq - - sudo apt-get install qtbase5-dev qtdeclarative5-dev libqt5webkit5-dev libsqlite3-dev - - sudo apt-get install qt5-default qttools5-dev-tools + - '[[ "$TRAVIS_OS_NAME" != linux || -z "$PPA" ]] || sudo add-apt-repository -y ppa:$PPA' + - '[ "$TRAVIS_OS_NAME" != linux ] || sudo apt-get -qy update' + - '[ "$TRAVIS_OS_NAME" != osx ] || brew update' + +install: + - '[ "$TRAVIS_OS_NAME" != linux ] || sudo apt-get -qy install cppcheck doxygen graphviz lcov' + - '[[ "$TRAVIS_OS_NAME" != linux || "$PPA" != */opt-* ]] || sudo apt-get -qy install qt${QT}base qt${QT}xmlpatterns' + - '[[ "$TRAVIS_OS_NAME" != linux || "$PPA" == */opt-* ]] || sudo apt-get -qy install qt5-qmake qtbase5-dev libqt5xmlpatterns5-dev' + - '[ "$TRAVIS_OS_NAME" != linux ] || gem install lcoveralls' + - '[ "$TRAVIS_OS_NAME" != osx ] || brew install cppcheck doxygen graphviz qt$BREW' + - '[ "$TRAVIS_OS_NAME" != osx ] || brew link --force qt$BREW' + - qmake -v + +before_script: + - '[[ "$TRAVIS_OS_NAME" != linux || "$CXX" != clang++ ]] || export QMAKESPEC=linux-clang' + - '[[ "$TRAVIS_OS_NAME" != linux || "$CXX" != g++ ]] || export QMAKESPEC=linux-g++' + - '[[ "$TRAVIS_OS_NAME" != osx || "$CXX" != clang++ ]] || export QMAKESPEC=macx-clang' + - '[[ "$TRAVIS_OS_NAME" != osx || "$CXX" != g++ ]] || export QMAKESPEC=macx-g++' + - '[[ "$TRAVIS_OS_NAME" != linux || "$PPA" != */opt-* ]] || . /opt/qt$QT/bin/qt$QT-env.sh' + - '[[ "$TRAVIS_OS_NAME" != linux || "$PPA" == */opt-* ]] || export QT_SELECT=qt5' + - mkdir -p "$TRAVIS_BUILD_DIR-build" + - qmake -o "$TRAVIS_BUILD_DIR-build" -r -Wall -Wlogic -Wparser CONFIG+=debug_and_release "$TRAVIS_BUILD_DIR" script: - - qmake nut.pro - - make + - make -C "$TRAVIS_BUILD_DIR-build" all + - make -C "$TRAVIS_BUILD_DIR-build" -j2 check TESTARGS=-silent diff --git a/nut.pri b/nut.pri index d479e7d..15b253b 100644 --- a/nut.pri +++ b/nut.pri @@ -1,5 +1,7 @@ QT += core sql +CONFIG += c++11 + INCLUDEPATH += $$PWD/include HEADERS += \ diff --git a/nut.pro b/nut.pro index 9603a19..9302c34 100644 --- a/nut.pro +++ b/nut.pro @@ -3,6 +3,7 @@ QT -= gui TARGET = nut TEMPLATE = lib +CONFIG += c++11 DEFINES += QT_DEPRECATED_WARNINGS diff --git a/src/changelogtable.h b/src/changelogtable.h index 27c4f70..84475a5 100644 --- a/src/changelogtable.h +++ b/src/changelogtable.h @@ -38,7 +38,7 @@ class ChangeLogTable : public Table NUT_DECLARE_FIELD(QString, version, version, setVersion) public: - ChangeLogTable(QObject *parentTableSet = Q_NULLPTR); + explicit ChangeLogTable(QObject *parentTableSet = Q_NULLPTR); }; NUT_END_NAMESPACE diff --git a/src/database.cpp b/src/database.cpp index 749aa83..0e2518a 100644 --- a/src/database.cpp +++ b/src/database.cpp @@ -52,7 +52,9 @@ NUT_BEGIN_NAMESPACE qulonglong DatabasePrivate::lastId = 0; QMap DatabasePrivate::allTableMaps; -DatabasePrivate::DatabasePrivate(Database *parent) : q_ptr(parent), isDatabaseNew(false) +DatabasePrivate::DatabasePrivate(Database *parent) : q_ptr(parent), + port(0), sqlGenertor(0), changeLogs(0), + isDatabaseNew(false) { } @@ -141,7 +143,7 @@ bool DatabasePrivate::updateDatabase() qDebug("Databse is changed"); QStringList sql = sqlGenertor->diff(last, current); - +qDebug()<<"database Sql =\n"<(); + currentModel.append( new TableModel(changeLogTypeId, __CHANGE_LOG_TABLE_NAME)); tables.insert(ChangeLogTable::staticMetaObject.className(), diff --git a/src/database.h b/src/database.h index 9dbc08e..1885be5 100644 --- a/src/database.h +++ b/src/database.h @@ -43,9 +43,9 @@ class NUT_EXPORT Database : public QObject Q_DECLARE_PRIVATE(Database) public: - Database(QObject *parent = 0); - Database(const Database &other); - Database(const QSqlDatabase &other); + explicit Database(QObject *parent = 0); + explicit Database(const Database &other); + explicit Database(const QSqlDatabase &other); ~Database(); bool open(); diff --git a/src/database_p.h b/src/database_p.h index 7c8709d..3299e4a 100644 --- a/src/database_p.h +++ b/src/database_p.h @@ -35,7 +35,7 @@ class DatabasePrivate Q_DECLARE_PUBLIC(Database) public: - DatabasePrivate(Database *parent); + explicit DatabasePrivate(Database *parent); bool open(bool updateDatabase); diff --git a/src/databasemodel.cpp b/src/databasemodel.cpp index e5adc6d..0902b7d 100644 --- a/src/databasemodel.cpp +++ b/src/databasemodel.cpp @@ -57,6 +57,10 @@ DatabaseModel::DatabaseModel(const QJsonObject &json) : } } +DatabaseModel::~DatabaseModel() +{ +} + TableModel *DatabaseModel::tableByName(QString tableName) const { for(int i = 0; i < size(); i++){ @@ -223,4 +227,16 @@ DatabaseModel *DatabaseModel::modelByName(const QString &name) return Q_NULLPTR; } +void DatabaseModel::deleteAllModels() +{ + QMapIterator i(_models); + while (i.hasNext()) { + i.next(); +// cout << i.key() << ": " << i.value() << endl; + delete i.value(); + } +// qDeleteAll(_models.values()); + _models.clear(); +} + NUT_END_NAMESPACE diff --git a/src/databasemodel.h b/src/databasemodel.h index c4e25b8..746b86d 100644 --- a/src/databasemodel.h +++ b/src/databasemodel.h @@ -43,6 +43,7 @@ public: DatabaseModel(const QString &name = QString::null); DatabaseModel(const DatabaseModel &other); DatabaseModel(const QJsonObject &json); + ~DatabaseModel(); TableModel *tableByName(QString tableName) const; TableModel *tableByClassName(QString className) const; @@ -69,6 +70,7 @@ public: void fixRelations(); static DatabaseModel *modelByName(const QString &name); + static void deleteAllModels(); }; NUT_END_NAMESPACE diff --git a/src/defines.h b/src/defines.h index c36ca4e..a779ccd 100644 --- a/src/defines.h +++ b/src/defines.h @@ -32,73 +32,77 @@ # define NUT_EXPORT Q_DECL_EXPORT #endif -#define NUT_INFO(type, name, value) \ - Q_CLASSINFO(__nut_NAME_PERFIX type #name #value, type "\n" #name "\n" #value) +#define NUT_INFO(type, name, value) \ + Q_CLASSINFO(__nut_NAME_PERFIX type #name #value, \ + type "\n" #name "\n" #value) // Database #define NUT_DB_VERSION(version) \ 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) \ - Q_PROPERTY(type* name READ name) \ - Q_PROPERTY(NUT_WRAP_NAMESPACE(TableSet) name##Table READ name##Table) \ - type* m_##name; \ - NUT_WRAP_NAMESPACE(TableSet) *m_##name##Table; \ -public: \ - static const type _##name; \ - type* name() const{ return m_##name; } \ - NUT_WRAP_NAMESPACE(TableSet) *name##Table() const { return m_##name##Table; } + Q_PROPERTY(type* name READ name) \ + Q_PROPERTY(NUT_WRAP_NAMESPACE(TableSet) name##Table READ name##Table)\ + type* m_##name; \ + NUT_WRAP_NAMESPACE(TableSet) *m_##name##Table; \ +public: \ + static const type _##name; \ + type* name() const{ return m_##name; } \ + NUT_WRAP_NAMESPACE(TableSet) *name##Table() const \ + { return m_##name##Table; } //Table -#define NUT_DECLARE_FIELD(type, name, read, write) \ - Q_PROPERTY(type name READ read WRITE write) \ - NUT_INFO(__nut_FIELD, name, 0) \ - type m_##name; \ -public: \ - static NUT_WRAP_NAMESPACE(FieldPhrase) name ## Field(){ \ - static NUT_WRAP_NAMESPACE(FieldPhrase) f = NUT_WRAP_NAMESPACE(FieldPhrase)(staticMetaObject.className(), #name); \ - return f; \ - } \ - type read() const{ \ - return m_##name; \ - } \ - void write(type name){ \ - m_##name = name; \ - propertyChanged(#name); \ +#define NUT_DECLARE_FIELD(type, name, read, write) \ + Q_PROPERTY(type name READ read WRITE write) \ + NUT_INFO(__nut_FIELD, name, 0) \ + type m_##name; \ +public: \ + static NUT_WRAP_NAMESPACE(FieldPhrase) name ## Field(){ \ + static NUT_WRAP_NAMESPACE(FieldPhrase) f = \ + NUT_WRAP_NAMESPACE(FieldPhrase) \ + (staticMetaObject.className(), #name); \ + return f; \ + } \ + type read() const{ \ + return m_##name; \ + } \ + void write(type name){ \ + m_##name = name; \ + propertyChanged(#name); \ } -#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) \ +#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) \ NUT_INFO(__nut_FOREGION_KEY, name, type) \ - type *m_##name; \ -public: \ - type *read() const { return m_##name ; } \ - void write(type *name){ \ - m_##name = name; \ + type *m_##name; \ +public: \ + type *read() const { return m_##name ; } \ + void write(type *name){ \ + m_##name = name; \ } -#define NUT_DECLARE_CHILD_TABLE(type, n) \ - private: \ - NUT_WRAP_NAMESPACE(TableSet) *m_##n; \ - public: \ - static type *n##Table(); \ +#define NUT_DECLARE_CHILD_TABLE(type, n) \ + private: \ + NUT_WRAP_NAMESPACE(TableSet) *m_##n; \ + public: \ + static type *n##Table(); \ NUT_WRAP_NAMESPACE(TableSet) *n(); -#define NUT_IMPLEMENT_CHILD_TABLE(class, type, n) \ - type *class::n##Table(){ \ - static type *f = new type(); \ - return f; \ - } \ - NUT_WRAP_NAMESPACE(TableSet) *class::n(){ \ - return m_##n; \ +#define NUT_IMPLEMENT_CHILD_TABLE(class, type, n) \ + type *class::n##Table(){ \ + static type *f = new type(); \ + return f; \ + } \ + NUT_WRAP_NAMESPACE(TableSet) *class::n(){ \ + return m_##n; \ } #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) \ +#define NUT_PRIMARY_AUTO_INCREMENT(x) NUT_PRIMARY_KEY(x) \ NUT_AUTO_INCREMENT(x) #define NUT_DISPLAY_NAME(field, name) NUT_INFO(__nut_DISPLAY, field, name) #define NUT_UNIQUE(x) NUT_INFO(__nut_UNIQUE, x, 0) diff --git a/src/defines_p.h b/src/defines_p.h index daab8be..045d001 100644 --- a/src/defines_p.h +++ b/src/defines_p.h @@ -21,9 +21,10 @@ #ifndef DEFINES_P_H #define DEFINES_P_H -#define __NAME "name" -#define __TYPE "type" -#define __FIELDS "fields" +#define __NAME "name" +#define __TYPE "type" +#define __FIELDS "fields" +#define __FOREIGN_KEYS "foreign_keys" #define __nut_FIELD "field" #define __nut_DB_VERSION "database_version" diff --git a/src/generators/mysqlgenerator.h b/src/generators/mysqlgenerator.h index d2224f4..c5916ba 100644 --- a/src/generators/mysqlgenerator.h +++ b/src/generators/mysqlgenerator.h @@ -29,7 +29,7 @@ NUT_BEGIN_NAMESPACE class MySqlGenerator : public SqlGeneratorBase { public: - MySqlGenerator(Database *parent = 0); + explicit MySqlGenerator(Database *parent = 0); QString fieldType(FieldModel *field); QString escapeValue(const QVariant &v) const; diff --git a/src/generators/postgresqlgenerator.h b/src/generators/postgresqlgenerator.h index 903cca8..028cea4 100644 --- a/src/generators/postgresqlgenerator.h +++ b/src/generators/postgresqlgenerator.h @@ -29,7 +29,7 @@ NUT_BEGIN_NAMESPACE class PostgreSqlGenerator : public SqlGeneratorBase { public: - PostgreSqlGenerator(Database *parent); + explicit PostgreSqlGenerator(Database *parent); QString fieldType(FieldModel *field); diff --git a/src/generators/sqlgeneratorbase.cpp b/src/generators/sqlgeneratorbase.cpp index 7cdbca8..ad64f94 100644 --- a/src/generators/sqlgeneratorbase.cpp +++ b/src/generators/sqlgeneratorbase.cpp @@ -70,7 +70,7 @@ QString SqlGeneratorBase::masterDatabaseName(QString databaseName) QString SqlGeneratorBase::createTable(TableModel *table) { - Q_UNUSED(table); + Q_UNUSED(table) return ""; } @@ -114,6 +114,13 @@ QString SqlGeneratorBase::fieldDeclare(FieldModel *field) return field->name + " " + fieldType(field) + (field->notNull ? " NOT NULL" : ""); } +QString SqlGeneratorBase::relationDeclare(const RelationModel *relation) +{ + return QString("FOREIGN KEY (FK_%1) REFERENCES %2(%1)") + .arg(relation->localColumn) + .arg(relation->slaveTable->name()); +} + QStringList SqlGeneratorBase::diff(DatabaseModel lastModel, DatabaseModel newModel) { @@ -125,9 +132,11 @@ QStringList SqlGeneratorBase::diff(DatabaseModel lastModel, TableModel *oldTable = lastModel.tableByName(table->name()); TableModel *newTable = newModel.tableByName(table->name()); QString sql = diff(oldTable, newTable); - if (!sql.isEmpty()) ret << sql; +// QString sqlRel = diffRelation(oldTable, newTable); +// if (!sqlRel.isEmpty()) +// ret << sqlRel; } return ret; @@ -161,14 +170,24 @@ QString SqlGeneratorBase::diff(TableModel *oldTable, TableModel *newTable) if (!newTable) return "DROP TABLE " + oldTable->name(); - QSet fieldNames; + QList fieldNames; + QList relations; - if (oldTable) + if (oldTable) { foreach (FieldModel *f, oldTable->fields()) - fieldNames.insert(f->name); + 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()) - fieldNames.insert(f->name); + if (!fieldNames.contains(f->name)) + fieldNames.append(f->name); + foreach (RelationModel *r, newTable->foregionKeys()) + if (!relations.contains(r->localColumn)) + relations.append(r->localColumn); QStringList columnSql; foreach (QString fieldName, fieldNames) { @@ -183,22 +202,104 @@ QString SqlGeneratorBase::diff(TableModel *oldTable, TableModel *newTable) columnSql << fieldDeclare(newField); } } +// foreach (QString fieldName, relations) { +// RelationModel *newRelation = newTable->foregionKeyByField(fieldName); +// if (oldTable) { +// RelationModel *oldRelation = oldTable->foregionKeyByField(fieldName); + +// QString buffer = diff(oldRelation, newRelation); +// if (!buffer.isNull()) +// columnSql << buffer; +// } else { +// columnSql << relationDeclare(newRelation); +// } +// } QString sql; if (oldTable) { - sql = QString("ALTER TABLE %1 \n%2").arg(newTable->name()).arg( - columnSql.join(",\n")); + sql = QString("ALTER TABLE %1 \n%2") + .arg(newTable->name()) + .arg(columnSql.join(",\n")); } else { if (!newTable->primaryKey().isNull()) columnSql << QString("CONSTRAINT pk_%1 PRIMARY KEY (%2)") .arg(newTable->name()) .arg(newTable->primaryKey()); - sql = QString("CREATE TABLE %1 \n(%2)").arg(newTable->name()).arg( - columnSql.join(",\n")); + sql = QString("CREATE TABLE %1 \n(%2)") + .arg(newTable->name()) + .arg(columnSql.join(",\n")); } return sql; } +QString SqlGeneratorBase::diffRelation(TableModel *oldTable, TableModel *newTable) +{ + if (!newTable) + return ""; + + QList relations; + + if (oldTable) + foreach (RelationModel *r, oldTable->foregionKeys()) + if (!relations.contains(r->localColumn)) + relations.append(r->localColumn); + + foreach (RelationModel *r, newTable->foregionKeys()) + if (!relations.contains(r->localColumn)) + relations.append(r->localColumn); + + QStringList columnSql; + foreach (QString fieldName, relations) { + RelationModel *newRelation = newTable->foregionKeyByField(fieldName); + RelationModel *oldRelation = 0; + if (oldTable) + oldRelation = oldTable->foregionKeyByField(fieldName); + + QString buffer = diff(oldRelation, newRelation); + if (!buffer.isNull()) + columnSql << buffer; + } + + if (columnSql.count()) + return "ALTER TABLE " + newTable->name() + "\n" + + columnSql.join(",\n"); + else + return ""; + +} + +QString SqlGeneratorBase::diff(RelationModel *oldRel, RelationModel *newRel) +{ + /* + CONSTRAINT FK_PersonOrder FOREIGN KEY (PersonID) + REFERENCES Persons(PersonID) + + ADD CONSTRAINT FK_%1 FOREIGN KEY (%1) REFERENCES %2(%3) + + return QString("ADD CONSTRAINT FK_%1 FOREIGN KEY (%1) " + "REFERENCES %2(%3)") + .arg(newRelation->localColumn) + .arg(newRelation->masterTable->name()) + .arg(newRelation->foreignColumn); + */ + if (!oldRel) + return QString("ADD CONSTRAINT FK_%1 FOREIGN KEY (%1) " + "REFERENCES %2(%3)") + .arg(newRel->localColumn) + .arg(newRel->masterTable->name()) + .arg(newRel->foreignColumn); + + if (!newRel) + return QString("ADD CONSTRAINT FK_%1 FOREIGN KEY (%1) " + "REFERENCES %2(%3)") + .arg(oldRel->localColumn) + .arg(oldRel->masterTable->name()) + .arg(oldRel->foreignColumn); + +// if (*oldRel == *newRel) + return ""; +} + QString SqlGeneratorBase::join(const QString &mainTable, const QList list, QStringList *order) @@ -235,7 +336,7 @@ QString SqlGeneratorBase::join(const QStringList &list, QStringList *order) //TODO: make this ungly code better and bugless :-) /* * Known issues: - * Support onle near joins, far supports with medium table finding not support yet + * Support only near joins, far supports with medium table finding not support yet */ if (!list.count()) @@ -466,6 +567,7 @@ QString SqlGeneratorBase::selectCommand(const QString &tableName, sql = sql.replace(_database->model().at(i)->className() + ".", _database->model().at(i)->name() + "."); + appendSkipTake(sql, skip, take); replaceTableNames(sql); return sql + " "; @@ -495,6 +597,7 @@ QString SqlGeneratorBase::selectCommand(const QString &tableName, sql = sql.replace(_database->model().at(i)->className() + ".", _database->model().at(i)->name() + "."); + appendSkipTake(sql, skip, take); replaceTableNames(sql); return sql + " "; @@ -826,6 +929,12 @@ SqlGeneratorBase::operatorString(const PhraseData::Condition &cond) const } } +void SqlGeneratorBase::appendSkipTake(QString &sql, int skip, int take) +{ + Q_UNUSED(sql); + Q_UNUSED(skip); + Q_UNUSED(take); +} QString SqlGeneratorBase::createConditionalPhrase(const PhraseData *d) const { @@ -852,7 +961,7 @@ QString SqlGeneratorBase::createConditionalPhrase(const PhraseData *d) const else if (op == PhraseData::AddMonths) ret = QString("DATEADD(month, %1, %2)") .arg(d->operand.toString()).arg(createConditionalPhrase(d->left)); - else if (op == PhraseData::AddYears) + else if (op == PhraseData::AddDays) ret = QString("DATEADD(day, %1, %2)") .arg(d->operand.toString()).arg(createConditionalPhrase(d->left)); else if (op == PhraseData::AddHours) diff --git a/src/generators/sqlgeneratorbase_p.h b/src/generators/sqlgeneratorbase_p.h index 897d251..1c5d98f 100644 --- a/src/generators/sqlgeneratorbase_p.h +++ b/src/generators/sqlgeneratorbase_p.h @@ -34,13 +34,14 @@ struct FieldModel; class DatabaseModel; class TableModel; class Database; -class RelationModel; +struct RelationModel; class SqlGeneratorBase : public QObject { // Q_OBJECT Database *_database; public: + //TODO: remove this enum enum CommandType{ Select, Insert, @@ -56,7 +57,7 @@ public: SignleField }; - SqlGeneratorBase(Database *parent); + explicit SqlGeneratorBase(Database *parent); virtual ~SqlGeneratorBase(); virtual QString masterDatabaseName(QString databaseName); @@ -65,10 +66,13 @@ public: virtual QString fieldType(FieldModel *field) = 0; virtual QString fieldDeclare(FieldModel *field); + virtual QString relationDeclare(const RelationModel *relation); virtual QStringList diff(DatabaseModel lastModel, 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 QString join(const QString &mainTable, const QList list, @@ -93,7 +97,8 @@ public: const int take = -1); virtual QString selectCommand(const QString &tableName, - const AgregateType &t, const QString &agregateArg, + const AgregateType &t, + const QString &agregateArg, const ConditionalPhrase &where, const QList &joins, const int skip = -1, @@ -119,8 +124,8 @@ public: virtual QVariant readValue(const QVariant::Type &type, const QVariant &dbValue); virtual QString phrase(const PhraseData *d) const; virtual QString operatorString(const PhraseData::Condition &cond) const; - -private: + virtual void appendSkipTake(QString &sql, int skip = -1, int take = -1); +protected: QString createConditionalPhrase(const PhraseData *d) const; QString createFieldPhrase(const PhraseList &ph); QString createOrderPhrase(const PhraseList &ph); diff --git a/src/generators/sqlitegenerator.cpp b/src/generators/sqlitegenerator.cpp index 9b71f2e..83ab286 100644 --- a/src/generators/sqlitegenerator.cpp +++ b/src/generators/sqlitegenerator.cpp @@ -71,24 +71,12 @@ QString SqliteGenerator::fieldType(FieldModel *field) return dbType; } -//QString SqliteGenerator::selectCommand(SqlGeneratorBase::AgregateType t, -// QString agregateArg, -// QString tableName, -// QList &wheres, -// QList &orders, -// QList joins, -// int skip, int take) -//{ -// QString command = SqlGeneratorBase::selectCommand(t, agregateArg, -// tableName, -// wheres, orders, -// joins, skip, take); - -// if (take != -1 && skip != -1) -// command.append(QString(" LIMIT %1 OFFSET %2") -// .arg(take) -// .arg(skip)); -// return command; -//} +void SqliteGenerator::appendSkipTake(QString &sql, int skip, int take) +{ + if (take != -1 && skip != -1) + sql.append(QString(" LIMIT %1 OFFSET %2") + .arg(take) + .arg(skip)); +} NUT_END_NAMESPACE diff --git a/src/generators/sqlitegenerator.h b/src/generators/sqlitegenerator.h index d1140a9..5969cde 100644 --- a/src/generators/sqlitegenerator.h +++ b/src/generators/sqlitegenerator.h @@ -29,15 +29,11 @@ NUT_BEGIN_NAMESPACE class SqliteGenerator : public SqlGeneratorBase { public: - SqliteGenerator(Database *parent = 0); + explicit SqliteGenerator(Database *parent = 0); QString fieldType(FieldModel *field); -// QString selectCommand(AgregateType t, QString agregateArg, -// QString tableName, -// QList &wheres, -// QList &orders, -// QList joins, int skip, int take); + void appendSkipTake(QString &sql, int skip, int take); }; NUT_END_NAMESPACE diff --git a/src/generators/sqlservergenerator.cpp b/src/generators/sqlservergenerator.cpp index 13f43fd..7d0e128 100644 --- a/src/generators/sqlservergenerator.cpp +++ b/src/generators/sqlservergenerator.cpp @@ -91,6 +91,7 @@ QString SqlServerGenerator::fieldType(FieldModel *field) break; default: + Q_UNREACHABLE(); dbType = ""; } @@ -125,7 +126,7 @@ QString SqlServerGenerator::escapeValue(const QVariant &v) const QPoint pt = v.toPoint(); return QString("geography::POINT(%1, %2, 4326)").arg(pt.x()).arg( pt.y()); - } else if (v.type() == QVariant::Point) { + } else if (v.type() == QVariant::PointF) { QPointF pt = v.toPointF(); return QString("geography::POINT(%1, %2, 4326)").arg(pt.x()).arg( pt.y()); @@ -133,23 +134,11 @@ QString SqlServerGenerator::escapeValue(const QVariant &v) const return SqlGeneratorBase::escapeValue(v); } -//QString SqlServerGenerator::selectCommand(SqlGeneratorBase::AgregateType t, -// QString agregateArg, -// QString tableName, -// QList &wheres, -// QList &orders, -// QList joins, int skip, int take) -//{ -// QString command = SqlGeneratorBase::selectCommand(t, agregateArg, -// tableName, -// wheres, orders, -// joins, skip, take); - -// if (take != -1 && skip != -1) -// command.append(QString("OFFSET %1 ROWS FETCH NEXT %2 ROWS ONLY") -// .arg(skip) -// .arg(take)); -// return command; -//} +void SqlServerGenerator::appendSkipTake(QString &sql, int skip, int take) +{ + if (take != -1 && skip != -1) + sql.append(QString(" OFFSET %1 ROWS FETCH NEXT %2 ROWS ONLY") + .arg(skip).arg(take)); +} NUT_END_NAMESPACE diff --git a/src/generators/sqlservergenerator.h b/src/generators/sqlservergenerator.h index db47268..4ef2f7c 100644 --- a/src/generators/sqlservergenerator.h +++ b/src/generators/sqlservergenerator.h @@ -29,7 +29,7 @@ NUT_BEGIN_NAMESPACE class SqlServerGenerator : public SqlGeneratorBase { public: - SqlServerGenerator(Database *parent = 0); + explicit SqlServerGenerator(Database *parent = 0); QString masterDatabaseName(QString databaseName); @@ -37,12 +37,8 @@ public: QString diff(FieldModel *oldField, FieldModel *newField); QString escapeValue(const QVariant &v) const; + void appendSkipTake(QString &sql, int skip, int take); -// QString selectCommand(AgregateType t, QString agregateArg, -// QString tableName, -// QList &wheres, -// QList &orders, -// QList joins, int skip, int take); }; NUT_END_NAMESPACE diff --git a/src/phrase.cpp b/src/phrase.cpp index 9c1ab02..274cdcc 100644 --- a/src/phrase.cpp +++ b/src/phrase.cpp @@ -24,45 +24,72 @@ NUT_BEGIN_NAMESPACE -#define LOG(s) qDebug() << __func__ << s; +#define LOG(s) qDebug() << __func__ << s + +PhraseData::PhraseData() : + className(""), fieldName(""), + type(Field), operatorCond(NotAssign), + left(0), right(0), operand(QVariant::Invalid), isNot(false), parents(1) +{ } PhraseData::PhraseData(const char *className, const char *fieldName) : className(className), fieldName(fieldName), type(Field), operatorCond(NotAssign), - left(0), right(0), operand(QVariant::Invalid), isNot(false) + left(0), right(0), operand(QVariant::Invalid), isNot(false), parents(1) { } PhraseData::PhraseData(PhraseData *l, PhraseData::Condition o) : className(0), fieldName(0), - type(WithoutOperand), operatorCond(o), left(new PhraseData(l)), right(0), isNot(false) -{ } + type(WithoutOperand), operatorCond(o), left(l), right(0), + isNot(false), parents(1) +{ + l->parents++; +} PhraseData::PhraseData(PhraseData *l, PhraseData::Condition o, - const PhraseData *r) + PhraseData *r) : className(0), fieldName(0), - type(WithOther), operatorCond(o), left(new PhraseData(l)), right(new PhraseData(r)), isNot(false) -{ } + type(WithOther), operatorCond(o), + left(l), right(r), + isNot(false), parents(1) +{ + l->parents++; + r->parents++; +} PhraseData::PhraseData(PhraseData *l, PhraseData::Condition o, QVariant r) : className(0), fieldName(0), - type(WithVariant), operatorCond(o), left(new PhraseData(l)), operand(r), isNot(false) + type(WithVariant), operatorCond(o), left(l), + right(0), operand(r), isNot(false), parents(1) { } -PhraseData::PhraseData(const PhraseData *other) +PhraseData *PhraseData::operator =(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; - if (type != Field) { - qDebug() << "Bug"; - } + LOG(""); + other->parents++; + return other; } +PhraseData &PhraseData::operator =(PhraseData &other) +{ + other.parents++; + 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 { return QString("[%1].%2").arg(className).arg(fieldName); @@ -78,10 +105,34 @@ PhraseData::~PhraseData() // if (left) // delete left; // } + +// if (right && !--right->parents) +// delete right; + +// if (left && !--left->parents) +// delete left; + LOG(""); } -AbstractFieldPhrase::AbstractFieldPhrase(const char *className, const char *fieldName) +void PhraseData::cleanUp() +{ +// cleanUp(this); +} + +void PhraseData::cleanUp(PhraseData *d) +{ + if (d->left) + cleanUp(d->left); + if (d->right) + cleanUp(d->right); +} + +AbstractFieldPhrase::AbstractFieldPhrase(PhraseData *d) : data(d) +{ } + +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) +{ + data = other.data; + data->parents++; + other.data = 0; } AbstractFieldPhrase::~AbstractFieldPhrase() { if (data) { - LOG(data->toString()); + LOG(data->toString()) << data->parents; } else { LOG(""); } if (data) { - delete data; - data = 0; + --data->parents; + if (data->parents <= 0) + delete data; } } @@ -118,9 +178,11 @@ ConditionalPhrase AbstractFieldPhrase::isNull() } -ConditionalPhrase AbstractFieldPhrase::operator ==(const ConditionalPhrase &other) +ConditionalPhrase AbstractFieldPhrase::operator ==(const ConditionalPhrase + &other) { - return ConditionalPhrase(this, PhraseData::Equal, const_cast(other)); + return ConditionalPhrase(this, PhraseData::Equal, + const_cast(other)); } #define AbstractFieldPhraseOperatorVariant(class, op, cond) \ @@ -147,9 +209,8 @@ AbstractFieldPhraseOperatorField(>=, PhraseData::GreaterEqual) AbstractFieldPhrase AbstractFieldPhrase::operator !() { - //TODO: classname and s + AbstractFieldPhrase f(data->className, data->fieldName); - f.data = new PhraseData(data); f.data->isNot = !data->isNot; return f; } @@ -169,60 +230,113 @@ PhraseList::PhraseList() : isValid(false) } -PhraseList::PhraseList(const PhraseList &other) +PhraseList::PhraseList(const PhraseList &other) : isValid(true) { + LOG(""); data = qMove(other.data); + const_cast(other).data.clear(); +} + +PhraseList::PhraseList(PhraseList &&other) +{ + LOG(""); + data = other.data; } PhraseList::PhraseList(const AbstractFieldPhrase &other) : isValid(true) { - data.append(new PhraseData(other.data)); + data.append(other.data); + incAllDataParents(); } -PhraseList::PhraseList(const AbstractFieldPhrase *left, const AbstractFieldPhrase &right) +PhraseList::PhraseList(const AbstractFieldPhrase *left, + const AbstractFieldPhrase &right) : isValid(true) { - data.append(new PhraseData(left->data)); - data.append(new PhraseData(right.data)); + data.append(left->data); + data.append(right.data); + incAllDataParents(); } PhraseList::PhraseList(PhraseList *left, PhraseList *right) : isValid(true) { - data = qMove(left->data + right->data); +// data = qMove(left->data + right->data); + data.append(left->data); + data.append(right->data); +// left->data.clear(); +// right->data.clear(); } PhraseList::PhraseList(PhraseList *left, const AbstractFieldPhrase *right) : isValid(true) { - data = left->data; - data.append(new PhraseData(right->data)); + data.append(left->data); + data.append(right->data); + incAllDataParents(); } PhraseList::~PhraseList() { -// data.clear(); + LOG(""); +} + +PhraseList &PhraseList::operator =(const PhraseList &other) +{ + data.append(const_cast(other).data); + return *this; } PhraseList PhraseList::operator |(const AbstractFieldPhrase &other) { return PhraseList(this, &other); } +void PhraseList::incAllDataParents() +{ +// foreach (PhraseData *d, data) +// d->parents++; +} + PhraseList PhraseList::operator |(PhraseList &other) { return PhraseList(this, &other); } -AssignmentPhrase::AssignmentPhrase(AbstractFieldPhrase *l, QVariant r) +AssignmentPhrase::AssignmentPhrase(PhraseData *d) : data(d) { + d->parents++; +} + +AssignmentPhrase::AssignmentPhrase(AbstractFieldPhrase *l, const QVariant r) +{ + data = new PhraseData(l->data, PhraseData::Equal, r); // l->data = 0; } -AssignmentPhrase::AssignmentPhrase(AbstractFieldPhrase *l, const AssignmentPhrase *r) +AssignmentPhrase::AssignmentPhrase(AbstractFieldPhrase *l, + const AssignmentPhrase *r) { data = new PhraseData(l->data, PhraseData::Equal, r->data); // l->data = 0; } +AssignmentPhrase::AssignmentPhrase(AssignmentPhrase *ph, const QVariant &v) +{ + data = new PhraseData(ph->data, PhraseData::Equal, v); +} + +//AssignmentPhrase::AssignmentPhrase(AssignmentPhrase &other) +//{ +// data = other.data; +// other.data = 0; +//} + +AssignmentPhrase::~AssignmentPhrase() +{ + if (data) + if (!--data->parents) + delete data; +} + //AssignmentPhrase::AssignmentPhrase(AssignmentPhrase *l, const AssignmentPhrase *r) //{ //// data = new PhraseData(l->data, PhraseData::Append, r->data); @@ -234,35 +348,70 @@ AssignmentPhraseList AssignmentPhrase::operator &(const AssignmentPhrase &other) return AssignmentPhraseList(this, &other); } +AssignmentPhraseList::AssignmentPhraseList() +{ + +} + AssignmentPhraseList::AssignmentPhraseList(const AssignmentPhrase &l) { data.append(l.data); + incAllDataParents(); } -AssignmentPhraseList::AssignmentPhraseList(AssignmentPhraseList *l, const AssignmentPhrase *r) +AssignmentPhraseList::AssignmentPhraseList(AssignmentPhraseList *l, + const AssignmentPhrase *r) { data.append(l->data); data.append(r->data); + incAllDataParents(); } -AssignmentPhraseList::AssignmentPhraseList(AssignmentPhrase *l, const AssignmentPhrase *r) +AssignmentPhraseList::AssignmentPhraseList(AssignmentPhrase *l, + const AssignmentPhrase *r) { data.append(l->data); data.append(r->data); + incAllDataParents(); } -AssignmentPhraseList AssignmentPhraseList::operator &(const AssignmentPhrase &ph) +AssignmentPhraseList::AssignmentPhraseList(const AssignmentPhrase &r, + const AssignmentPhrase &l) +{ + data.append(l.data); + data.append(r.data); + incAllDataParents(); +} + +AssignmentPhraseList AssignmentPhraseList::operator &(const AssignmentPhrase + &ph) { return AssignmentPhraseList(this, &ph); } +AssignmentPhraseList::~AssignmentPhraseList() +{ + foreach (PhraseData *d, data) + if (!--d->parents) + delete d; +// qDeleteAll(data); + // data.clear(); +} + +void AssignmentPhraseList::incAllDataParents() +{ + foreach (PhraseData *d, data) + d->parents++; +} + ConditionalPhrase::ConditionalPhrase() : data(0) { } ConditionalPhrase::ConditionalPhrase(const ConditionalPhrase &other) { qDebug() << "************* ctor called:"; - this->data = new PhraseData(other.data); + data = other.data; + data->parents++; // const_cast(other).data = 0; } @@ -276,7 +425,8 @@ ConditionalPhrase::ConditionalPhrase(const ConditionalPhrase &&other) ConditionalPhrase::ConditionalPhrase(const PhraseData *data) { - this->data = new PhraseData(data); + this->data = const_cast(data); + this->data->parents++; } ConditionalPhrase::ConditionalPhrase(AbstractFieldPhrase *l, @@ -335,13 +485,17 @@ ConditionalPhrase::ConditionalPhrase(ConditionalPhrase *l, ConditionalPhrase::~ConditionalPhrase() { LOG(""); - if (data) - delete data; + if (data) { + data->cleanUp(); + if (!--data->parents) + delete data; + } } -ConditionalPhrase ConditionalPhrase::operator =(const ConditionalPhrase &other) +ConditionalPhrase &ConditionalPhrase::operator =(const ConditionalPhrase &other) { - this->data = new PhraseData(other.data); + data = other.data; + data->parents++; return *this; } @@ -350,22 +504,75 @@ ConditionalPhrase ConditionalPhrase::operator ==(const QVariant &other) return ConditionalPhrase(this, PhraseData::Equal, other); } -ConditionalPhrase ConditionalPhrase::operator ==(const AbstractFieldPhrase &other) -{ - return ConditionalPhrase(this, PhraseData::Equal, other); +//ConditionalPhrase ConditionalPhrase::operator ==(const AbstractFieldPhrase &other) +//{ +// return ConditionalPhrase(this, PhraseData::Equal, other); +//} + +//ConditionalPhrase ConditionalPhrase::operator &&(const ConditionalPhrase &other) +//{ +// return ConditionalPhrase(this, PhraseData::And, +// const_cast(other)); +//} + +//ConditionalPhrase ConditionalPhrase::operator ||(const ConditionalPhrase &other) +//{ +// return ConditionalPhrase(this, PhraseData::Or, +// const_cast(other)); +//} + +#define DECLARE_CONDITIONALPHRASE_OPERATORS(op, cond) \ +ConditionalPhrase operator op(const ConditionalPhrase &l, \ + const ConditionalPhrase &r) \ +{ \ + ConditionalPhrase p; \ + p.data = new PhraseData; \ + p.data->operatorCond = cond; \ + p.data->left = l.data; \ + p.data->right = r.data; \ + l.data->parents++; \ + r.data->parents++; \ + return p; \ +} \ +ConditionalPhrase operator op(const ConditionalPhrase &l, \ + ConditionalPhrase &&r) \ +{ \ + ConditionalPhrase p; \ + p.data = new PhraseData; \ + p.data->operatorCond = cond; \ + p.data->left = l.data; \ + p.data->right = r.data; \ + l.data->parents++; \ + r.data->parents++; \ + return p; \ +} \ +ConditionalPhrase operator op(ConditionalPhrase &&l, \ + const ConditionalPhrase &r) \ +{ \ + ConditionalPhrase p; \ + p.data = new PhraseData; \ + p.data->operatorCond = cond; \ + p.data->left = l.data; \ + p.data->right = r.data; \ + l.data->parents++; \ + r.data->parents++; \ + return p; \ +} \ +ConditionalPhrase operator op(ConditionalPhrase &&l, ConditionalPhrase &&r) \ +{ \ + ConditionalPhrase p; \ + p.data = new PhraseData; \ + p.data->operatorCond = cond; \ + p.data->left = l.data; \ + p.data->right = r.data; \ + l.data->parents++; \ + r.data->parents++; \ + return p; \ } -ConditionalPhrase ConditionalPhrase::operator &&(const ConditionalPhrase &other) -{ - return ConditionalPhrase(this, PhraseData::And, - const_cast(other)); -} - -ConditionalPhrase ConditionalPhrase::operator ||(const ConditionalPhrase &other) -{ - return ConditionalPhrase(this, PhraseData::Or, - const_cast(other)); -} +DECLARE_CONDITIONALPHRASE_OPERATORS(==, PhraseData::Equal) +DECLARE_CONDITIONALPHRASE_OPERATORS(||, PhraseData::Or) +DECLARE_CONDITIONALPHRASE_OPERATORS(&&, PhraseData::And) ConditionalPhrase ConditionalPhrase::operator !() { @@ -374,4 +581,63 @@ ConditionalPhrase ConditionalPhrase::operator !() return f; } +PhraseDataList::PhraseDataList() : QList() +{ + +} + +PhraseDataList::PhraseDataList(const PhraseDataList &other) : QList() +{ + PhraseDataList &o = const_cast(other); + PhraseDataList::iterator i; + for (i = o.begin(); i != o.end(); ++i) + append(*i); +} + +void PhraseDataList::append(PhraseData *d) +{ + d->parents++; + QList::append(d); +} + +void PhraseDataList::append(QList &dl) +{ + foreach (PhraseData *d, dl) + d->parents++; + QList::append(dl); +} + +PhraseDataList::~PhraseDataList() +{ + QList::iterator i; + for (i = begin(); i != end(); ++i) { + (*i)->cleanUp(); + if (!--(*i)->parents) + delete *i; + } +} + +//AssignmentPhraseList operator &(const AssignmentPhrase &l, const AssignmentPhrase &r) +//{ +// return AssignmentPhraseList(l, r); +//} + +//AssignmentPhraseList operator &(const AssignmentPhrase &l, AssignmentPhrase &&r) +//{ +// r.data = 0; +// return AssignmentPhraseList(l, r); +//} + +//AssignmentPhraseList operator &(AssignmentPhrase &&l, const AssignmentPhrase &r) +//{ +// l.data = 0; +// return AssignmentPhraseList(l, r); +//} + +//AssignmentPhraseList operator &(AssignmentPhrase &&l, AssignmentPhrase &&r) +//{ +// r.data = l.data = 0; +// return AssignmentPhraseList(l, r); +//} + NUT_END_NAMESPACE diff --git a/src/phrase.h b/src/phrase.h index 2e45c25..c466d9d 100644 --- a/src/phrase.h +++ b/src/phrase.h @@ -25,7 +25,7 @@ #include #include #include -#if __cplusplus >= 201103L +#ifdef Q_COMPILER_INITIALIZER_LISTS # include #endif @@ -91,71 +91,111 @@ public: const char *fieldName; Type type; - Condition operatorCond; - const PhraseData *left; - const PhraseData *right; + PhraseData *left; + PhraseData *right; QVariant operand; + Condition operatorCond; bool isNot; + quint16 parents; + PhraseData(); PhraseData(const char *className, const char *fieldName); PhraseData(PhraseData *l, Condition o); - PhraseData(PhraseData *l, Condition o, const PhraseData *r); + PhraseData(PhraseData *l, Condition o, PhraseData *r); PhraseData(PhraseData *l, Condition o, QVariant r); +// explicit PhraseData(const PhraseData &other); +// explicit PhraseData(const PhraseData *other); - PhraseData(const PhraseData *other); + PhraseData *operator =(PhraseData *other); + PhraseData &operator =(PhraseData &other); QString toString() const; ~PhraseData(); + + void cleanUp(); +private: + void cleanUp(PhraseData *d); +}; + +class PhraseDataList : public QList +{ +public: + PhraseDataList(); + PhraseDataList(const PhraseDataList &other); + void append(PhraseData *d); + void append(QList &dl); + virtual ~PhraseDataList(); }; class AssignmentPhraseList { public: QList data; + explicit AssignmentPhraseList(); AssignmentPhraseList(const AssignmentPhrase &l); AssignmentPhraseList(AssignmentPhraseList *l, const AssignmentPhrase *r); AssignmentPhraseList(AssignmentPhrase *l, const AssignmentPhrase *r); + AssignmentPhraseList(const AssignmentPhrase &r, const AssignmentPhrase &l); AssignmentPhraseList operator &(const AssignmentPhrase &ph); + + ~AssignmentPhraseList(); + +private: + void incAllDataParents(); }; class AssignmentPhrase { public: PhraseData *data; - AssignmentPhrase(AbstractFieldPhrase *l, QVariant r); - AssignmentPhrase(AbstractFieldPhrase *l, const AssignmentPhrase *r); + explicit AssignmentPhrase(PhraseData *d); + explicit AssignmentPhrase(AbstractFieldPhrase *l, const QVariant r); + explicit AssignmentPhrase(AbstractFieldPhrase *l, const AssignmentPhrase *r); + explicit AssignmentPhrase(AssignmentPhrase *ph, const QVariant &v); +// explicit AssignmentPhrase(AssignmentPhrase &other); + ~AssignmentPhrase(); // AssignmentPhrase(AssignmentPhrase *l, const AssignmentPhrase *r); AssignmentPhraseList operator &(const AssignmentPhrase &other); }; +//AssignmentPhraseList operator &(const AssignmentPhrase &l, const AssignmentPhrase &r); +//AssignmentPhraseList operator &(const AssignmentPhrase &l, AssignmentPhrase &&r); +//AssignmentPhraseList operator &(AssignmentPhrase &&l, const AssignmentPhrase &r); +//AssignmentPhraseList operator &(AssignmentPhrase &&l, AssignmentPhrase &&r); + class PhraseList{ public: bool isValid; - QList data; - PhraseList(); + PhraseDataList data; + explicit PhraseList(); PhraseList(const PhraseList &other); + PhraseList(PhraseList &&other); PhraseList(const AbstractFieldPhrase &other); PhraseList(const AbstractFieldPhrase *left, const AbstractFieldPhrase &right); PhraseList(PhraseList *left, PhraseList *right); PhraseList(PhraseList *left, const AbstractFieldPhrase *right); virtual ~PhraseList(); + PhraseList &operator =(const PhraseList &other); PhraseList operator |(PhraseList &other); PhraseList operator |(const AbstractFieldPhrase &other); + +private: + void incAllDataParents(); }; class ConditionalPhrase { public: PhraseData *data; - QSharedPointer leftDataPointer; - QSharedPointer rightDataPointer; +// QSharedPointer leftDataPointer; +// QSharedPointer rightDataPointer; ConditionalPhrase(); ConditionalPhrase(const ConditionalPhrase &other); #ifdef Q_COMPILER_RVALUE_REFS @@ -171,11 +211,11 @@ public: ConditionalPhrase(ConditionalPhrase *l, PhraseData::Condition cond, ConditionalPhrase &r); virtual ~ConditionalPhrase(); - ConditionalPhrase operator =(const ConditionalPhrase &other); + ConditionalPhrase &operator =(const ConditionalPhrase &other); ConditionalPhrase operator ==(const QVariant &other); - ConditionalPhrase operator ==(const AbstractFieldPhrase &other); - ConditionalPhrase operator &&(const ConditionalPhrase &other); - ConditionalPhrase operator ||(const ConditionalPhrase &other); +// ConditionalPhrase operator ==(const AbstractFieldPhrase &other); +// ConditionalPhrase operator &&(const ConditionalPhrase &other); +// ConditionalPhrase operator ||(const ConditionalPhrase &other); ConditionalPhrase operator !(); SPECIALIZATION_NUMERIC_MEMBER(type, <, PhraseData::Less) @@ -184,12 +224,24 @@ public: SPECIALIZATION_NUMERIC_MEMBER(type, >=, PhraseData::GreaterEqual) }; +#define DECLARE_CONDITIONALPHRASE_OPERATORS(op) \ +ConditionalPhrase operator op(const ConditionalPhrase &l, const ConditionalPhrase &r); \ +ConditionalPhrase operator op(const ConditionalPhrase &l, ConditionalPhrase &&r); \ +ConditionalPhrase operator op(ConditionalPhrase &&l, const ConditionalPhrase &r); \ +ConditionalPhrase operator op(ConditionalPhrase &&l, ConditionalPhrase &&r); + +DECLARE_CONDITIONALPHRASE_OPERATORS(==) +DECLARE_CONDITIONALPHRASE_OPERATORS(&&) +DECLARE_CONDITIONALPHRASE_OPERATORS(||) + class AbstractFieldPhrase { public: PhraseData *data; + explicit AbstractFieldPhrase(PhraseData *d); AbstractFieldPhrase(const char *className, const char *fieldName); AbstractFieldPhrase(const AbstractFieldPhrase &other); + AbstractFieldPhrase(AbstractFieldPhrase &&other); virtual ~AbstractFieldPhrase(); @@ -257,8 +309,8 @@ public: return ConditionalPhrase(this, PhraseData::Like, term); } - AssignmentPhrase operator =(const QVariant &other) { - return AssignmentPhrase(this, other); + AssignmentPhrase operator =(const QVariant &v) { + return AssignmentPhrase(this, v); } }; @@ -309,6 +361,32 @@ SPECIALIZATION_NUMERIC(qreal) return ConditionalPhrase(this, cond, val); \ } +template<> +class FieldPhrase : public AbstractFieldPhrase +{ +public: + FieldPhrase(const char *className, const char *s) : + AbstractFieldPhrase(className, s) + {} + + AssignmentPhrase operator =(const bool &other) { + return AssignmentPhrase(this, other); + } + + FieldPhrase operator !() + { + FieldPhrase f(data->className, data->fieldName); +// f.data = new PhraseData(data); + f.data->isNot = !data->isNot; + return f; + } + + operator ConditionalPhrase() + { + return ConditionalPhrase(this, PhraseData::Equal, !data->isNot); + } +}; + template<> class FieldPhrase : public AbstractFieldPhrase { diff --git a/src/query.cpp b/src/query.cpp index eacf1ba..f8c79fd 100644 --- a/src/query.cpp +++ b/src/query.cpp @@ -23,7 +23,7 @@ NUT_BEGIN_NAMESPACE QueryPrivate::QueryPrivate(QueryBase *parent) : q_ptr(parent), - skip(-1), take(-1) + database(0), tableSet(0), skip(-1), take(-1) { } diff --git a/src/query.h b/src/query.h index 786f0e9..8ab8c54 100644 --- a/src/query.h +++ b/src/query.h @@ -50,7 +50,7 @@ template bool m_autoDelete; public: - Query(Database *database, TableSetBase *tableSet, bool autoDelete); + explicit Query(Database *database, TableSetBase *tableSet, bool autoDelete); ~Query(); //ddl @@ -73,9 +73,6 @@ public: Query *where(const ConditionalPhrase &ph); Query *setWhere(const ConditionalPhrase &ph); - Query *include(TableSetBase *t); - Query *include(Table *t); - //data selecting T *first(); QList toList(int count = -1); @@ -124,8 +121,8 @@ template Q_OUTOFLINE_TEMPLATE Query::~Query() { Q_D(Query); + qDebug() << "~Query";// << d->sql; delete d; - qDebug() << "~Query"; } template @@ -139,7 +136,7 @@ Q_OUTOFLINE_TEMPLATE QList Query::toList(int count) d->sql = d->database->sqlGenertor()->selectCommand( d->tableName, d->fieldPhrase, d->wherePhrase, d->orderPhrase, d->relations, d->skip, d->take); -qDebug() <sql; + QSqlQuery q = d->database->exec(d->sql); if (q.lastError().isValid()) { qDebug() << q.lastError().text(); @@ -419,8 +416,8 @@ Q_OUTOFLINE_TEMPLATE Query *Query::join(const QString &className) .relationByClassNames(className, d->className); if (!rel) { - qInfo("No relation between %s and %s", - qPrintable(d->className), qPrintable(className)); + qDebug() << "No relation between" << d->className + << "and" << className; return this; } @@ -496,20 +493,6 @@ Q_OUTOFLINE_TEMPLATE Query *Query::orderBy(const PhraseList &ph) return this; } -template -Q_OUTOFLINE_TEMPLATE Query *Query::include(TableSetBase *t) -{ - Q_D(Query); - return this; -} - -template -Q_OUTOFLINE_TEMPLATE Query *Query::include(Table *t) -{ - Q_D(Query); - return this; -} - template Q_OUTOFLINE_TEMPLATE int Query::update(const AssignmentPhraseList &ph) { diff --git a/src/query_p.h b/src/query_p.h index 75c8f3b..f7127cc 100644 --- a/src/query_p.h +++ b/src/query_p.h @@ -31,13 +31,13 @@ NUT_BEGIN_NAMESPACE class Database; class TableSetBase; class QueryBase; -class RelationModel; +struct RelationModel; class QueryPrivate{ QueryBase *q_ptr; Q_DECLARE_PUBLIC(QueryBase) public: - QueryPrivate(QueryBase *parent); + explicit QueryPrivate(QueryBase *parent); ~QueryPrivate(); QString sql; diff --git a/src/sqlmodel.cpp b/src/sqlmodel.cpp index ff40fa3..9f1a870 100644 --- a/src/sqlmodel.cpp +++ b/src/sqlmodel.cpp @@ -85,4 +85,9 @@ QVariant SqlModel::data(const QModelIndex &index, int role) const return QVariant(); } +SqlModelPrivate::SqlModelPrivate() +{ + +} + NUT_END_NAMESPACE diff --git a/src/sqlmodel.h b/src/sqlmodel.h index e7c5e60..e8c2590 100644 --- a/src/sqlmodel.h +++ b/src/sqlmodel.h @@ -36,7 +36,7 @@ class SqlModel : public QAbstractTableModel Q_OBJECT public: - SqlModel(Database *database, TableSetBase *tableSet, QObject *parent = Q_NULLPTR); + explicit SqlModel(Database *database, TableSetBase *tableSet, QObject *parent = Q_NULLPTR); int rowCount(const QModelIndex &parent) const; int columnCount(const QModelIndex &parent) const; diff --git a/src/sqlmodel_p.h b/src/sqlmodel_p.h index edd8dc8..7b68e88 100644 --- a/src/sqlmodel_p.h +++ b/src/sqlmodel_p.h @@ -13,6 +13,8 @@ class SqlModelPrivate { SqlModel *q_ptr; Q_DECLARE_PUBLIC(SqlModel) public: + explicit SqlModelPrivate(); + QString tableName; QList rows; diff --git a/src/table.cpp b/src/table.cpp index eeea6ec..e3deae5 100644 --- a/src/table.cpp +++ b/src/table.cpp @@ -39,7 +39,7 @@ NUT_BEGIN_NAMESPACE * This should be fixed to v1.2 */ -Table::Table(QObject *parent) : QObject(parent), myModel(0) +Table::Table(QObject *parent) : QObject(parent), myModel(0), _parentTableSet(0) { setStatus(NewCreated); } diff --git a/src/tablemodel.cpp b/src/tablemodel.cpp index 4f428bc..b77c173 100644 --- a/src/tablemodel.cpp +++ b/src/tablemodel.cpp @@ -90,7 +90,7 @@ QList TableModel::fields() const QList TableModel::foregionKeys() const { - return _foregionKeys; + return _foreignKeys; } QStringList TableModel::fieldsNames() const @@ -237,9 +237,9 @@ TableModel::TableModel(int typeId, QString tableName) fk->slaveTable = this; fk->localColumn = name + "Id"; fk->localProperty = name; - fk->foregionColumn = value; + fk->foreignColumn = value; fk->masterClassName = value; - _foregionKeys.append(fk); + _foreignKeys.append(fk); } if(type == __nut_FIELD){ @@ -292,6 +292,7 @@ TableModel::TableModel(QJsonObject json, QString tableName) _name = tableName; QJsonObject fields = json.value(__FIELDS).toObject(); + QJsonObject relations = json.value(__FOREIGN_KEYS).toObject(); foreach (QString key, fields.keys()) { QJsonObject fieldObject = fields.value(key).toObject(); FieldModel *f = new FieldModel; @@ -309,19 +310,31 @@ TableModel::TableModel(QJsonObject json, QString tableName) _fields.append(f); } - if(json.keys().contains(__nut_AUTO_INCREMENT)) - field(json.value(__nut_AUTO_INCREMENT).toString())->isAutoIncrement = true; + foreach (QString key, relations.keys()) { + QJsonObject relObject = fields.value(key).toObject(); + _foreignKeys.append(new RelationModel(relObject)); + } - if(json.keys().contains(__nut_PRIMARY_KEY)) - field(json.value(__nut_PRIMARY_KEY).toString())->isAutoIncrement = true; +// if(json.keys().contains(__nut_AUTO_INCREMENT)) +// field(json.value(__nut_AUTO_INCREMENT).toString())->isAutoIncrement = true; + +// if(json.keys().contains(__nut_PRIMARY_KEY)) +// field(json.value(__nut_PRIMARY_KEY).toString())->isAutoIncrement = true; _allModels.insert(this); } +TableModel::~TableModel() +{ + qDeleteAll(_fields); + qDeleteAll(_foreignKeys); +} + QJsonObject TableModel::toJson() const { QJsonObject obj; QJsonObject fieldsObj; + QJsonObject foreignKeysObj; foreach (FieldModel *f, _fields) { QJsonObject fieldObj; @@ -337,28 +350,41 @@ QJsonObject TableModel::toJson() const if(!f->defaultValue.isNull()) fieldObj.insert(__nut_DEFAULT_VALUE, f->defaultValue); - fieldsObj.insert(f->name, fieldObj); - if(f->isAutoIncrement) - obj.insert(__nut_PRIMARY_KEY, f->name); + obj.insert(__nut_AUTO_INCREMENT, f->name); if(f->isPrimaryKey) - obj.insert(__nut_AUTO_INCREMENT, f->name); + obj.insert(__nut_PRIMARY_KEY, f->name); + + fieldsObj.insert(f->name, fieldObj); } + foreach (RelationModel *rel, _foreignKeys) + foreignKeysObj.insert(rel->localColumn, rel->toJson()); + obj.insert(__FIELDS, fieldsObj); + obj.insert(__FOREIGN_KEYS, foreignKeysObj); return obj; } -RelationModel *TableModel::foregionKey(QString otherTable) const +RelationModel *TableModel::foregionKey(const QString &otherTable) const { - foreach (RelationModel *fk, _foregionKeys) + foreach (RelationModel *fk, _foreignKeys) if(fk->masterClassName == otherTable) return fk; return 0; } +RelationModel *TableModel::foregionKeyByField(const QString &fieldName) const +{ + foreach (RelationModel *fk, _foreignKeys) + if(fk->localColumn == fieldName) + return fk; + + return 0; +} + QString TableModel::toString() const { QStringList sl; @@ -379,4 +405,61 @@ QString TableModel::primaryKey() const return QString::null; } +FieldModel::FieldModel(const QJsonObject &json) +{ + name = json.value(__NAME).toString(); + type = static_cast(json.value(__TYPE).toInt()); + length = json.value(__nut_LEN).toInt(); + notNull = json.value(__nut_NOT_NULL).toBool(); + isAutoIncrement = json.value(__nut_AUTO_INCREMENT).toBool(); + isPrimaryKey = json.value(__nut_PRIMARY_KEY).toBool(); + defaultValue = json.value(__nut_DEFAULT_VALUE).toString(); + isUnique = json.value(__nut_UNIQUE).toBool(); +} + +QJsonObject FieldModel::toJson() const +{ + QJsonObject fieldObj; + fieldObj.insert(__NAME, name); + fieldObj.insert(__TYPE, QString(QVariant::typeToName(type))); + fieldObj.insert(__nut_LEN, length); + fieldObj.insert(__nut_NOT_NULL, notNull); + fieldObj.insert(__nut_AUTO_INCREMENT, isAutoIncrement); + fieldObj.insert(__nut_PRIMARY_KEY, isPrimaryKey); + fieldObj.insert(__nut_DEFAULT_VALUE, defaultValue); + return fieldObj; +} + +RelationModel::RelationModel(const QJsonObject &obj) +{ + localColumn = obj.value("localColumn").toString(); + localProperty = obj.value("localProperty").toString(); + masterClassName = obj.value("masterClassName").toString(); + foreignColumn = obj.value("foreignColumn").toString(); + slaveTable = masterTable = 0; +} + +QJsonObject RelationModel::toJson() const +{ + QJsonObject o; + o.insert("localColumn", localColumn); + o.insert("localProperty", localProperty); + o.insert("masterClassName", masterClassName); + o.insert("foreignColumn", foreignColumn); + return o; +} + +bool operator ==(const RelationModel &l, const RelationModel &r) +{ + return r.foreignColumn == l.foreignColumn + && r.localColumn == l.localColumn + && r.localProperty == l.localColumn + && r.masterClassName == l.masterClassName; +} + +bool operator !=(const RelationModel &l, const RelationModel &r) +{ + return !(l == r); +} + NUT_END_NAMESPACE diff --git a/src/tablemodel.h b/src/tablemodel.h index e089ed2..3a4ec06 100644 --- a/src/tablemodel.h +++ b/src/tablemodel.h @@ -31,12 +31,14 @@ NUT_BEGIN_NAMESPACE class TableModel; struct FieldModel{ - FieldModel() : name(QString::null), length(0), defaultValue(QString::null), + explicit FieldModel() : name(QString::null), length(0), defaultValue(QString::null), notNull(false), isPrimaryKey(false), isAutoIncrement(false), isUnique(false) { } + explicit FieldModel(const QJsonObject &json); + QString name; //TODO: QMetaType::Type?? QVariant::Type type; @@ -63,25 +65,36 @@ struct FieldModel{ bool operator !=(const FieldModel &f) const{ return !(*this == f); } + + QJsonObject toJson() const; }; struct RelationModel{ + RelationModel() : localColumn(""), localProperty(""), slaveTable(0), + foreignColumn(""), masterTable(0), masterClassName("") + {} + explicit RelationModel(const QJsonObject &obj); + //slave QString localColumn; QString localProperty; TableModel *slaveTable; //master - QString foregionColumn; + QString foreignColumn; TableModel *masterTable; QString masterClassName; + + QJsonObject toJson() const; }; -class TableModel +bool operator ==(const RelationModel &l, const RelationModel &r); +bool operator !=(const RelationModel &l, const RelationModel &r); +class TableModel { public: - - TableModel(int typeId, QString tableName = QString::null); - TableModel(QJsonObject json, QString tableName); + explicit TableModel(int typeId, QString tableName = QString::null); + explicit TableModel(QJsonObject json, QString tableName); + virtual ~TableModel(); QJsonObject toJson() const; @@ -91,7 +104,8 @@ public: FieldModel *field(int n) const; FieldModel *field(QString name) const; - RelationModel *foregionKey(QString otherTable) const; + RelationModel *foregionKey(const QString &otherTable) const; + RelationModel *foregionKeyByField(const QString &fieldName) const; QString toString() const; @@ -122,7 +136,7 @@ private: QString _className; int _typeId; QList _fields; - QList _foregionKeys; + QList _foreignKeys; static QSet_allModels; bool checkClassInfo(const QMetaClassInfo &classInfo, QString &type, QString &name, QString &value); diff --git a/src/tableset.h b/src/tableset.h index d62fe73..8034a09 100644 --- a/src/tableset.h +++ b/src/tableset.h @@ -39,8 +39,8 @@ template class NUT_EXPORT TableSet : public TableSetBase { public: - TableSet(Database *parent); - TableSet(Table *parent); + explicit TableSet(Database *parent); + explicit TableSet(Table *parent); void append(T *t); void append(QList t); diff --git a/src/tablesetbase_p.h b/src/tablesetbase_p.h index 801c11b..df95a71 100644 --- a/src/tablesetbase_p.h +++ b/src/tablesetbase_p.h @@ -35,8 +35,8 @@ class TableSetBase : public QObject { public: - TableSetBase(Database *parent); - TableSetBase(Table *parent); + explicit TableSetBase(Database *parent); + explicit TableSetBase(Table *parent); virtual int save(Database *db, bool cleanUp = false); void clearChilds(); diff --git a/src/types/dbgeography.h b/src/types/dbgeography.h index 9a7dfd0..3fd834a 100644 --- a/src/types/dbgeography.h +++ b/src/types/dbgeography.h @@ -35,8 +35,8 @@ class NUT_EXPORT DbGeography public: explicit DbGeography(); - DbGeography(const DbGeography &other); - DbGeography(const QVariant &value); + explicit DbGeography(const DbGeography &other); + explicit DbGeography(const QVariant &value); qreal longitude() const; qreal latitude() const; diff --git a/src/wherephrase.cpp b/src/wherephrase.cpp deleted file mode 100644 index 3a3213e..0000000 --- a/src/wherephrase.cpp +++ /dev/null @@ -1,234 +0,0 @@ -/************************************************************************** -** -** This file is part of Nut project. -** https://github.com/HamedMasafi/Nut -** -** Nut is free software: you can redistribute it and/or modify -** it under the terms of the GNU Lesser General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** Nut is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU Lesser General Public License for more details. -** -** You should have received a copy of the GNU Lesser General Public License -** along with Nut. If not, see . -** -**************************************************************************/ - -#include -#include - -#include "phrase.h" - -NUT_BEGIN_NAMESPACE - -PhraseData::PhraseData(const char *className, const char *s) -{ - Q_UNUSED(className) - text = QString("[%1].%2").arg(className).arg(s); - type = Field; - operatorCond = NotAssign; -} - -PhraseData::PhraseData(PhraseData *l, PhraseData::Condition o) : left(l) -{ - operatorCond = o; - type = WithoutOperand; -} - -PhraseData::PhraseData(PhraseData *l, PhraseData::Condition o, - const PhraseData *r) - : left(l), right(r) -{ - operatorCond = o; - type = WithOther; -} - -PhraseData::PhraseData(PhraseData *l, PhraseData::Condition o, QVariant r) - : left(l), operand(r) -{ - operatorCond = o; - type = WithVariant; -} - -PhraseData::~PhraseData() -{ - if (type == WithOther) { - delete left; - delete right; - } - if (type == WithVariant) { - if (left) - delete left; - } -} - -PhraseData *WherePhrase::data() const -{ - return _data; -} - -WherePhrase::WherePhrase(const char *className, const char *s) -{ - _data = new PhraseData(className, s); -} - -WherePhrase::WherePhrase(const WherePhrase &l) -{ - _data = l._data; - _dataPointer = QSharedPointer(l._dataPointer); -} - -WherePhrase::WherePhrase(WherePhrase *l) -{ - _data = l->_data; - - l->_data = 0; - l->_dataPointer.reset(0); -} - -WherePhrase::WherePhrase(WherePhrase *l, PhraseData::Condition o) -{ - _data = new PhraseData(l->_data, o); - l->_data = 0; - l->_dataPointer.reset(0); -} - -WherePhrase::WherePhrase(WherePhrase *l, PhraseData::Condition o, - WherePhrase *r) -{ - _data = new PhraseData(l->_data, o, r->_data); - l->_data = 0; - r->_data = 0; - - l->_dataPointer.reset(0); - r->_dataPointer.reset(0); -} - -WherePhrase::WherePhrase(WherePhrase *l, PhraseData::Condition o, QVariant r) -{ - _data = new PhraseData(l->_data, o, r); - l->_data = 0; - l->_dataPointer.reset(0); -} - -WherePhrase::~WherePhrase() -{ -} - -WherePhrase WherePhrase::operator==(const WherePhrase &other) -{ - return WherePhrase(this, PhraseData::Equal, (WherePhrase *)&other); -} - -WherePhrase WherePhrase::operator!=(const WherePhrase &other) -{ - return WherePhrase(this, PhraseData::NotEqual, (WherePhrase *)&other); -} - -WherePhrase WherePhrase::operator<(const WherePhrase &other) -{ - return WherePhrase(this, PhraseData::Less, (WherePhrase *)&other); -} - -WherePhrase WherePhrase::operator>(const WherePhrase &other) -{ - return WherePhrase(this, PhraseData::Greater, (WherePhrase *)&other); -} - -WherePhrase WherePhrase::operator<=(const WherePhrase &other) -{ - return WherePhrase(this, PhraseData::LessEqual, (WherePhrase *)&other); -} - -WherePhrase WherePhrase::operator>=(const WherePhrase &other) -{ - return WherePhrase(this, PhraseData::GreaterEqual, (WherePhrase *)&other); -} - -WherePhrase WherePhrase::operator!() -{ - if (_data->operatorCond < 20) - _data->operatorCond - = (PhraseData::Condition)((_data->operatorCond + 10) % 20); - else - qFatal("Operator ! can not aplied to non condition statements"); - - return this; // WherePhrase(this, PhraseData::Not); -} - -WherePhrase WherePhrase::operator=(const WherePhrase &other) -{ - return WherePhrase(this, PhraseData::Set, (WherePhrase *)&other); -} - -WherePhrase WherePhrase::operator+(const WherePhrase &other) -{ - return WherePhrase(this, PhraseData::Add, (WherePhrase *)&other); -} - -WherePhrase WherePhrase::operator-(const WherePhrase &other) -{ - return WherePhrase(this, PhraseData::Minus, (WherePhrase *)&other); -} - -WherePhrase WherePhrase::operator*(const WherePhrase &other) -{ - return WherePhrase(this, PhraseData::Multiple, (WherePhrase *)&other); -} - -WherePhrase WherePhrase::operator/(const WherePhrase &other) -{ - return WherePhrase(this, PhraseData::Divide, (WherePhrase *)&other); -} - -WherePhrase WherePhrase::operator&&(const WherePhrase &other) -{ - return WherePhrase(this, PhraseData::And, (WherePhrase *)&other); -} - -WherePhrase WherePhrase::operator||(const WherePhrase &other) -{ - return WherePhrase(this, PhraseData::Or, (WherePhrase *)&other); -} - -WherePhrase WherePhrase::operator&(const WherePhrase &other) -{ - return WherePhrase(this, PhraseData::Append, (WherePhrase *)&other); -} - -WherePhrase WherePhrase::operator==(const QVariant &other) -{ - return WherePhrase(this, PhraseData::Equal, other); -} - -WherePhrase WherePhrase::operator!=(const QVariant &other) -{ - return WherePhrase(this, PhraseData::NotEqual, other); -} - -WherePhrase WherePhrase::operator<(const QVariant &other) -{ - return WherePhrase(this, PhraseData::Less, other); -} - -WherePhrase WherePhrase::operator>(const QVariant &other) -{ - return WherePhrase(this, PhraseData::Greater, other); -} - -WherePhrase WherePhrase::operator<=(const QVariant &other) -{ - return WherePhrase(this, PhraseData::LessEqual, other); -} - -WherePhrase WherePhrase::operator>=(const QVariant &other) -{ - return WherePhrase(this, PhraseData::GreaterEqual, other); -} - - -NUT_END_NAMESPACE diff --git a/src/wherephrase.h b/src/wherephrase.h deleted file mode 100644 index 8d33b75..0000000 --- a/src/wherephrase.h +++ /dev/null @@ -1,515 +0,0 @@ -/************************************************************************** -** -** This file is part of Nut project. -** https://github.com/HamedMasafi/Nut -** -** Nut is free software: you can redistribute it and/or modify -** it under the terms of the GNU Lesser General Public License as published by -** the Free Software Foundation, either version 3 of the License, or -** (at your option) any later version. -** -** Nut is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU Lesser General Public License for more details. -** -** You should have received a copy of the GNU Lesser General Public License -** along with Nut. If not, see . -** -**************************************************************************/ - -#ifndef WHEREPHRASE_H -#define WHEREPHRASE_H - -#include - -#include -#include -#include -#include -#include -#include -#include "defines.h" -#include "types/dbgeography.h" - -#if __cplusplus >= 201103L -#include -#endif - -NUT_BEGIN_NAMESPACE - -class SqlGeneratorBase; -//class PhraseData -//{ -//public: -// enum Condition { -// NotAssign = 0, -// Equal, -// Less, -// LessEqual, -// Null, -// In, -// Like, - -// Not = 10, -// NotEqual, -// GreaterEqual, -// Greater, -// NotNull, -// NotIn, -// NotLike, - -// And = 20, -// Or, - -// Append, -// Set, - -// Add, -// Minus, -// Multiple, -// Divide, - -// // special types -// Distance -// }; - -// enum Type { Field, WithVariant, WithOther, WithoutOperand }; -// Type type; - -// Condition operatorCond; - -// QString text; -// const PhraseData *left; -// const PhraseData *right; -// QVariant operand; - -// PhraseData(const char *className, const char *s); -// PhraseData(PhraseData *l, Condition o); -// PhraseData(PhraseData *l, Condition o, const PhraseData *r); -// PhraseData(PhraseData *l, Condition o, QVariant r); - -// ~PhraseData(); -//}; - -class WherePhrase -{ -protected: - PhraseData *_data; - QSharedPointer _dataPointer; - -public: - WherePhrase(const char *className, const char *s); - - WherePhrase(const WherePhrase &l); - WherePhrase(WherePhrase *l); - WherePhrase(WherePhrase *l, PhraseData::Condition o); - WherePhrase(WherePhrase *l, PhraseData::Condition o, WherePhrase *r); - WherePhrase(WherePhrase *l, PhraseData::Condition o, QVariant r); - - ~WherePhrase(); - - WherePhrase operator==(const WherePhrase &other); - WherePhrase operator!=(const WherePhrase &other); - WherePhrase operator<(const WherePhrase &other); - WherePhrase operator>(const WherePhrase &other); - WherePhrase operator<=(const WherePhrase &other); - WherePhrase operator>=(const WherePhrase &other); - - WherePhrase operator==(const QVariant &other); - WherePhrase operator!=(const QVariant &other); - WherePhrase operator<(const QVariant &other); - WherePhrase operator>(const QVariant &other); - WherePhrase operator<=(const QVariant &other); - WherePhrase operator>=(const QVariant &other); - - WherePhrase operator!(); - WherePhrase operator=(const WherePhrase &other); - - WherePhrase operator+(const WherePhrase &other); - WherePhrase operator-(const WherePhrase &other); - WherePhrase operator*(const WherePhrase &other); - WherePhrase operator/(const WherePhrase &other); - - WherePhrase operator&&(const WherePhrase &other); - WherePhrase operator||(const WherePhrase &other); - - WherePhrase operator&(const WherePhrase &other); - - PhraseData *data() const; -}; - -template -class FieldPhrase : public WherePhrase -{ -public: - FieldPhrase(const char *className, const char *s); - - WherePhrase operator=(const FieldPhrase &other); - - WherePhrase operator=(const WherePhrase &other); - WherePhrase operator=(const QVariant &other); - WherePhrase operator+(const QVariant &other); - WherePhrase operator!(); - - WherePhrase operator==(const QVariant &other); - WherePhrase operator!=(const QVariant &other); - WherePhrase operator<(const QVariant &other); - WherePhrase operator>(const QVariant &other); - WherePhrase operator<=(const QVariant &other); - WherePhrase operator>=(const QVariant &other); - - WherePhrase isNull(); - WherePhrase in(QList list); - // WherePhrase in(QStringList list); - WherePhrase like(QString pattern); -}; - -template -Q_OUTOFLINE_TEMPLATE FieldPhrase::FieldPhrase(const char *className, - const char *s) - : WherePhrase(className, s) -{ - // qDebug() << "(" << this << ")" << "FieldPhrase ctor" << className << - // s; -} - -template -Q_OUTOFLINE_TEMPLATE WherePhrase FieldPhrase:: -operator=(const QVariant &other) -{ - return WherePhrase(this, PhraseData::Set, other); -} - -template -Q_OUTOFLINE_TEMPLATE WherePhrase -FieldPhrase::operator=(const FieldPhrase &other) -{ - return WherePhrase(this, PhraseData::Equal, &other); -} - -template -Q_OUTOFLINE_TEMPLATE WherePhrase FieldPhrase:: -operator=(const WherePhrase &other) -{ - return WherePhrase(this, PhraseData::Set, &other); -} - -template -Q_OUTOFLINE_TEMPLATE WherePhrase FieldPhrase:: -operator+(const QVariant &other) -{ - return WherePhrase(this, PhraseData::Add, other); -} - -template -Q_OUTOFLINE_TEMPLATE WherePhrase FieldPhrase::operator!() -{ - if (_data->operatorCond < 20) - _data->operatorCond - = (PhraseData::Condition)((_data->operatorCond + 10) % 20); - else - qFatal("Operator ! can not aplied to non condition statements"); - - return this; // WherePhrase(this, PhraseData::Not); -} - -template -Q_OUTOFLINE_TEMPLATE WherePhrase FieldPhrase:: -operator==(const QVariant &other) -{ - return WherePhrase(this, PhraseData::Equal, other); -} - -template -Q_OUTOFLINE_TEMPLATE WherePhrase FieldPhrase:: -operator!=(const QVariant &other) -{ - return WherePhrase(this, PhraseData::NotEqual, other); -} - -template -Q_OUTOFLINE_TEMPLATE WherePhrase FieldPhrase:: -operator<(const QVariant &other) -{ - return WherePhrase(this, PhraseData::Less, other); -} - -template -Q_OUTOFLINE_TEMPLATE WherePhrase FieldPhrase:: -operator>(const QVariant &other) -{ - return WherePhrase(this, PhraseData::Greater, other); -} - -template -Q_OUTOFLINE_TEMPLATE WherePhrase FieldPhrase:: -operator<=(const QVariant &other) -{ - return WherePhrase(this, PhraseData::LessEqual, other); -} - -template -Q_OUTOFLINE_TEMPLATE WherePhrase FieldPhrase:: -operator>=(const QVariant &other) -{ - return WherePhrase(this, PhraseData::GreaterEqual, other); -} - -template -Q_OUTOFLINE_TEMPLATE WherePhrase FieldPhrase::isNull() -{ - return WherePhrase(this, PhraseData::Null); -} - -template -Q_OUTOFLINE_TEMPLATE WherePhrase FieldPhrase::in(QList list) -{ - QVariantList vlist; - foreach (T t, list) - vlist.append(QVariant::fromValue(t)); - - return WherePhrase(this, PhraseData::In, vlist); -} - -// template -// Q_OUTOFLINE_TEMPLATE WherePhrase FieldPhrase::in(QStringList list) -//{ -// return WherePhrase(this, PhraseData::In, list); -//} - -template -Q_OUTOFLINE_TEMPLATE WherePhrase FieldPhrase::like(QString pattern) -{ - return WherePhrase(this, PhraseData::Like, pattern); -} - -// Custom types -template <> -class FieldPhrase : public WherePhrase -{ -public: - FieldPhrase(const char *className, const char *s) - : WherePhrase(className, s) - { - } - - WherePhrase distance(const DbGeography &geo) - { - return WherePhrase(this, PhraseData::Distance, - QVariant::fromValue(geo)); - } -}; - -// Custom types -template <> -class FieldPhrase : public WherePhrase -{ -public: - FieldPhrase(const char *className, const char *s) - : WherePhrase(className, s) - { - } - - WherePhrase distance(const QPoint &geo) - { - return WherePhrase(this, PhraseData::Distance, - QVariant::fromValue(geo)); - } - WherePhrase operator=(const QPoint &other) - { - return WherePhrase(this, PhraseData::Set, other); - } -}; - -// Custom types -template <> -class FieldPhrase : public WherePhrase -{ -public: - FieldPhrase(const char *className, const char *s) - : WherePhrase(className, s) - { - } - - WherePhrase distance(const QPointF &geo) - { - return WherePhrase(this, PhraseData::Distance, - QVariant::fromValue(geo)); - } - WherePhrase operator=(const QPointF &other) - { - return WherePhrase(this, PhraseData::Set, other); - } -}; - -// template<> -// class FieldPhrase: public WherePhrase { -// public: -// FieldPhrase(const char *className, const char* s) : WherePhrase(className, -// s){ - -// } - -// WherePhrase like(QString pattern) -// { -// return WherePhrase(this, PhraseData::Like, pattern); -// } -//}; - -template <> -class FieldPhrase : public WherePhrase -{ -public: - FieldPhrase(const char *className, const char *s) - : WherePhrase(className, s) - { - } - - WherePhrase operator==(const bool &other) - { - return WherePhrase(this, PhraseData::Equal, other ? 1 : 0); - } - - WherePhrase operator=(const bool &other) - { - return WherePhrase(this, PhraseData::Set, other ? 1 : 0); - } - - WherePhrase operator!() - { - return WherePhrase(this, PhraseData::Equal, 0); - } -}; - -class NumericFieldPhrase : public WherePhrase -{ -public: - NumericFieldPhrase(const char *className, const char *s) - : WherePhrase(className, s) - { - } - - WherePhrase operator=(const QVariant &other) - { - return WherePhrase(this, PhraseData::Set, other); - } - - WherePhrase operator+(const QVariant &other) - { - return WherePhrase(this, PhraseData::Add, other); - } - - WherePhrase operator-(const QVariant &other) - { - return WherePhrase(this, PhraseData::Minus, other); - } - - WherePhrase operator++() - { - return WherePhrase(this, PhraseData::Add, 1); - } - - WherePhrase operator--() - { - return WherePhrase(this, PhraseData::Minus, 1); - } - - WherePhrase operator==(const QVariant &other) - { - return WherePhrase(this, PhraseData::Equal, other); - } - - WherePhrase operator!=(const QVariant &other) - { - return WherePhrase(this, PhraseData::NotEqual, other); - } - - WherePhrase operator<(const QVariant &other) - { - return WherePhrase(this, PhraseData::Less, other); - } - - WherePhrase operator>(const QVariant &other) - { - return WherePhrase(this, PhraseData::Greater, other); - } - - WherePhrase operator<=(const QVariant &other) - { - return WherePhrase(this, PhraseData::LessEqual, other); - } - - WherePhrase operator>=(const QVariant &other) - { - return WherePhrase(this, PhraseData::GreaterEqual, other); - } - - WherePhrase isNull() - { - return WherePhrase(this, PhraseData::Null); - } - - template - WherePhrase in(QList list) - { - QVariantList vlist; - foreach (T t, list) - vlist.append(QVariant::fromValue(t)); - return WherePhrase(this, PhraseData::In, vlist); - } - -#if __cplusplus >= 201103L - template - WherePhrase in(std::initializer_list list) - { - return in(QList(list)); - } -#endif - - WherePhrase in(int count, ...) - { - QVariantList vlist; - - va_list ap; - va_start(ap, count); - - for (int i = 0; i < count; ++i) - vlist.append(QVariant::fromValue(va_arg(ap, int))); - - va_end(ap); - - return WherePhrase(this, PhraseData::In, vlist); - } -}; - -#define SPECIALIZATION_NUMERIC(type) \ - template <> \ - class FieldPhrase : public NumericFieldPhrase \ - { \ - public: \ - FieldPhrase(const char *className, const char *s) \ - : NumericFieldPhrase(className, s) \ - { \ - } \ - WherePhrase operator=(const WherePhrase &other) \ - { \ - return WherePhrase(this, PhraseData::Set, (WherePhrase *)&other); \ - } \ - }; - -SPECIALIZATION_NUMERIC(qint8) -SPECIALIZATION_NUMERIC(qint16) -SPECIALIZATION_NUMERIC(qint32) -SPECIALIZATION_NUMERIC(qint64) - -SPECIALIZATION_NUMERIC(quint8) -SPECIALIZATION_NUMERIC(quint16) -SPECIALIZATION_NUMERIC(quint32) -SPECIALIZATION_NUMERIC(quint64) - -SPECIALIZATION_NUMERIC(qreal) - -NUT_END_NAMESPACE - -#endif // PHRASE_H diff --git a/test/basic/maintest.cpp b/test/basic/maintest.cpp index 5bc22f3..74f5d14 100644 --- a/test/basic/maintest.cpp +++ b/test/basic/maintest.cpp @@ -69,6 +69,7 @@ void MainTest::createUser() void MainTest::createPost() { + TIC(); Post *newPost = new Post; newPost->setTitle("post title"); newPost->setSaveDate(QDateTime::currentDateTime()); @@ -93,6 +94,7 @@ void MainTest::createPost() postId = newPost->id(); QTEST_ASSERT(newPost->id() != 0); + TOC(); qDebug() << "New post inserted with id:" << newPost->id(); } @@ -119,6 +121,26 @@ void MainTest::createPost2() qDebug() << "New post2 inserted with id:" << newPost->id(); } +void MainTest::updatePostOnTheFly() +{ + auto c = db.postTable()->query() + ->where(Post::idField() == postId) + ->update(Post::titleField() = "New title"); + + QTEST_ASSERT(c == 1); +} + +void MainTest::selectPublicts() +{ + auto q = db.postTable()->query() + ->where(Post::isPublicField()) + ->toList(); + + auto q2 = db.postTable()->query() + ->where(!Post::isPublicField()) + ->toList(); +} + void MainTest::selectPosts() { auto q = db.postTable()->query() @@ -187,7 +209,7 @@ void MainTest::testDate() db.postTable()->append(newPost); - db.saveChanges(); + db.saveChanges(true); auto q = db.postTable()->query() ->setWhere(Post::idField() == newPost->id()) @@ -247,4 +269,13 @@ void MainTest::emptyDatabase() QTEST_ASSERT(commentsCount == 6); } +void MainTest::cleanupTestCase() +{ + post->deleteLater(); + user->deleteLater(); + + qDeleteAll(TableModel::allModels()); + DatabaseModel::deleteAllModels(); +} + QTEST_MAIN(MainTest) diff --git a/test/basic/maintest.h b/test/basic/maintest.h index 5a56759..67ec06b 100644 --- a/test/basic/maintest.h +++ b/test/basic/maintest.h @@ -27,16 +27,20 @@ private slots: void createUser(); void createPost(); void createPost2(); + void selectPublicts(); void join(); void selectPosts(); void selectScoreAverage(); void selectFirst(); void selectPostsWithoutTitle(); void selectPostIds(); + void updatePostOnTheFly(); void testDate(); void selectWithInvalidRelation(); void modifyPost(); void emptyDatabase(); + + void cleanupTestCase(); }; #endif // MAINTEST_H diff --git a/test/common/post.h b/test/common/post.h index ddf7936..7759b8c 100644 --- a/test/common/post.h +++ b/test/common/post.h @@ -27,6 +27,7 @@ class Post : public Table NUT_DECLARE_FIELD(QDateTime, saveDate, saveDate, setSaveDate) NUT_DECLARE_FIELD(QString, body, body, setBody) + NUT_DECLARE_FIELD(bool, isPublic, isPublic, setPublic) NUT_DECLARE_CHILD_TABLE(Comment, comments) NUT_DECLARE_CHILD_TABLE(Score, scores)