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..9d5983b 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"<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()) @@ -858,7 +959,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 ab9223c..d0aa239 100644 --- a/src/generators/sqlgeneratorbase_p.h +++ b/src/generators/sqlgeneratorbase_p.h @@ -41,6 +41,7 @@ class SqlGeneratorBase : public QObject 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, @@ -120,7 +125,7 @@ public: virtual QString phrase(const PhraseData *d) const; virtual QString operatorString(const PhraseData::Condition &cond) const; virtual void appendSkipTake(QString &sql, int skip = -1, int take = -1); -private: +protected: QString createConditionalPhrase(const PhraseData *d) const; QString createFieldPhrase(const PhraseList &ph); QString createOrderPhrase(const PhraseList &ph); diff --git a/src/generators/sqlitegenerator.h b/src/generators/sqlitegenerator.h index 1a28c32..5969cde 100644 --- a/src/generators/sqlitegenerator.h +++ b/src/generators/sqlitegenerator.h @@ -29,7 +29,7 @@ NUT_BEGIN_NAMESPACE class SqliteGenerator : public SqlGeneratorBase { public: - SqliteGenerator(Database *parent = 0); + explicit SqliteGenerator(Database *parent = 0); QString fieldType(FieldModel *field); 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..4a00030 100644 --- a/src/phrase.cpp +++ b/src/phrase.cpp @@ -26,6 +26,12 @@ NUT_BEGIN_NAMESPACE #define LOG(s) qDebug() << __func__ << s; +PhraseData::PhraseData() : + className(""), fieldName(""), + type(Field), operatorCond(NotAssign), + left(0), right(0), operand(QVariant::Invalid), isNot(false) +{ } + PhraseData::PhraseData(const char *className, const char *fieldName) : className(className), fieldName(fieldName), type(Field), operatorCond(NotAssign), @@ -45,23 +51,20 @@ PhraseData::PhraseData(PhraseData *l, PhraseData::Condition o, 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(new PhraseData(l)), right(0), operand(r), isNot(false) { } -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; - if (type != Field) { - qDebug() << "Bug"; - } -} +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) +{ } + +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) +{ } QString PhraseData::toString() const { @@ -169,7 +172,7 @@ PhraseList::PhraseList() : isValid(false) } -PhraseList::PhraseList(const PhraseList &other) +PhraseList::PhraseList(const PhraseList &other) : isValid(true) { data = qMove(other.data); } @@ -211,7 +214,10 @@ PhraseList PhraseList::operator |(PhraseList &other) { return PhraseList(this, &other); } -AssignmentPhrase::AssignmentPhrase(AbstractFieldPhrase *l, QVariant r) +AssignmentPhrase::AssignmentPhrase(PhraseData *d) : data(d) +{ } + +AssignmentPhrase::AssignmentPhrase(AbstractFieldPhrase *l, const QVariant r) { data = new PhraseData(l->data, PhraseData::Equal, r); // l->data = 0; @@ -223,6 +229,23 @@ AssignmentPhrase::AssignmentPhrase(AbstractFieldPhrase *l, const AssignmentPhras // 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) + delete data; +} + //AssignmentPhrase::AssignmentPhrase(AssignmentPhrase *l, const AssignmentPhrase *r) //{ //// data = new PhraseData(l->data, PhraseData::Append, r->data); @@ -234,6 +257,11 @@ AssignmentPhraseList AssignmentPhrase::operator &(const AssignmentPhrase &other) return AssignmentPhraseList(this, &other); } +AssignmentPhraseList::AssignmentPhraseList() +{ + +} + AssignmentPhraseList::AssignmentPhraseList(const AssignmentPhrase &l) { data.append(l.data); @@ -251,11 +279,23 @@ AssignmentPhraseList::AssignmentPhraseList(AssignmentPhrase *l, const Assignment data.append(r->data); } +AssignmentPhraseList::AssignmentPhraseList(const AssignmentPhrase &r, const AssignmentPhrase &l) +{ + data.append(l.data); + data.append(r.data); +} + AssignmentPhraseList AssignmentPhraseList::operator &(const AssignmentPhrase &ph) { return AssignmentPhraseList(this, &ph); } +AssignmentPhraseList::~AssignmentPhraseList() +{ +// qDeleteAll(data); +// data.clear(); +} + ConditionalPhrase::ConditionalPhrase() : data(0) { } @@ -339,7 +379,7 @@ ConditionalPhrase::~ConditionalPhrase() delete data; } -ConditionalPhrase ConditionalPhrase::operator =(const ConditionalPhrase &other) +ConditionalPhrase &ConditionalPhrase::operator =(const ConditionalPhrase &other) { this->data = new PhraseData(other.data); return *this; @@ -350,22 +390,67 @@ 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 = new PhraseData(l.data); \ + p.data->right = new PhraseData(r.data); \ + return p; \ +} \ +ConditionalPhrase operator op(const ConditionalPhrase &l, ConditionalPhrase &&r) \ +{ \ + ConditionalPhrase p; \ + p.data = new PhraseData; \ + p.data->operatorCond = cond; \ + p.data->left = new PhraseData(l.data); \ + p.data->right = r.data; \ + r.data = 0; \ + 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; \ + l.data = 0; \ + p.data->right = new PhraseData(r.data); \ + 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 = r.data = 0; \ + 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 +459,27 @@ ConditionalPhrase ConditionalPhrase::operator !() return f; } +//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..df12f7b 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,20 +91,21 @@ public: const char *fieldName; Type type; - Condition operatorCond; const PhraseData *left; const PhraseData *right; QVariant operand; + Condition operatorCond; bool isNot; + 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, QVariant r); - - PhraseData(const PhraseData *other); + explicit PhraseData(const PhraseData &other); + explicit PhraseData(const PhraseData *other); QString toString() const; @@ -115,30 +116,43 @@ 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(); }; 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(); + explicit PhraseList(); PhraseList(const PhraseList &other); PhraseList(const AbstractFieldPhrase &other); PhraseList(const AbstractFieldPhrase *left, const AbstractFieldPhrase &right); @@ -171,11 +185,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,6 +198,16 @@ 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: @@ -257,8 +281,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 +333,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 33e9174..29a5031 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 @@ -124,8 +124,8 @@ template Q_OUTOFLINE_TEMPLATE Query::~Query() { Q_D(Query); + qDebug() << "~Query";// << d->sql; delete d; - qDebug() << "~Query"; } template @@ -419,8 +419,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; } @@ -520,7 +520,7 @@ Q_OUTOFLINE_TEMPLATE int Query::update(const AssignmentPhraseList &ph) ph, d->wherePhrase); QSqlQuery q = d->database->exec(d->sql); - +qDebug() << d->sql; if (m_autoDelete) deleteLater(); return q.numRowsAffected(); diff --git a/src/query_p.h b/src/query_p.h index 75c8f3b..1bb2b16 100644 --- a/src/query_p.h +++ b/src/query_p.h @@ -37,7 +37,7 @@ class QueryPrivate{ 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..b42269a 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,11 +310,16 @@ 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); } @@ -322,6 +328,7 @@ QJsonObject TableModel::toJson() const { QJsonObject obj; QJsonObject fieldsObj; + QJsonObject foreignKeysObj; foreach (FieldModel *f, _fields) { QJsonObject fieldObj; @@ -337,28 +344,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 +399,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..c2439c5 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,35 @@ 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; }; +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); QJsonObject toJson() const; @@ -91,7 +103,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 +135,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..a8a75be 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() diff --git a/test/basic/maintest.h b/test/basic/maintest.h index 5a56759..c79ce1a 100644 --- a/test/basic/maintest.h +++ b/test/basic/maintest.h @@ -27,12 +27,14 @@ 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(); 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)