From f87923ff9511489eefafc949c47e28e701c0dc72 Mon Sep 17 00:00:00 2001 From: Hamed Masafi Date: Sat, 21 May 2016 12:39:03 +0430 Subject: [PATCH] Read me edited --- README.md | 9 +- nut.pri | 12 +- src.tar.gz | Bin 0 -> 16959 bytes src/changelogtable.cpp | 1 + src/changelogtable.h | 2 +- src/database.cpp | 142 ++++++++------- src/database.h | 3 +- src/databasemodel.cpp | 66 +++++-- src/databasemodel.h | 24 ++- src/defines.h | 40 ++--- src/defines_p.h | 3 +- src/mysqlgenerator.cpp | 53 ++++-- src/mysqlgenerator.h | 24 ++- src/postgresqlgenerator.cpp | 73 +++++--- src/postgresqlgenerator.h | 28 ++- src/query.h | 115 ++++++------ src/querybase_p.h | 2 +- src/sqlgeneratorbase.cpp | 123 ++++++++++--- src/sqlgeneratorbase_p.h | 55 ++++-- src/sqlitegenerator.cpp | 42 +++-- src/sqlitegenerator.h | 24 ++- src/sqlservergenerator.cpp | 103 ++++++++++- src/sqlservergenerator.h | 36 +++- src/table.cpp | 78 +++----- src/table.h | 10 +- src/tablemodel.cpp | 108 +++++------ src/tablemodel.h | 49 ++--- src/tableset.h | 7 +- src/tablesetbase.cpp | 23 ++- src/tablesetbase_p.h | 5 + src/wherephrase.cpp | 347 +++++++++++++++++++++++++++++++++++- src/wherephrase.h | 153 +++++++++++++++- test/.maintest.cpp.kate-swp | Bin 341 -> 0 bytes test/comment.h | 1 + test/maintest.cpp | 93 +++++++--- test/maintest.h | 5 +- test/post.h | 2 + test/weblogdatabase.h | 2 +- 38 files changed, 1414 insertions(+), 449 deletions(-) create mode 100644 src.tar.gz delete mode 100644 test/.maintest.cpp.kate-swp diff --git a/README.md b/README.md index 3cb8a38..651f839 100644 --- a/README.md +++ b/README.md @@ -15,11 +15,13 @@ ```cpp autoq = FROM(db.posts()) - WHERE(Post::id() == %1) - BIND(postId); + WHERE(Post::idField() == postId); + auto posts = q->toList(); // now posts is a QList contain all posts in // database that has id equal to postId variable +auto post = q->first(); +// post is first row in database that its id is equal to postId ``` ### Adding to database: @@ -41,8 +43,7 @@ db.saveChanges(); ### Modify database data: ```cpp auto q = FROM(db.posts()) - WHERE(Post::id() == %1) - BIND(postId); + WHERE(Post::idField() == postId); Post *post = q->first(); diff --git a/nut.pri b/nut.pri index d7bddb3..82e7dbe 100644 --- a/nut.pri +++ b/nut.pri @@ -10,7 +10,6 @@ HEADERS += \ $$PWD/src/defines_p.h \ $$PWD/src/defines.h \ $$PWD/src/query.h \ - $$PWD/src/tablescheema.h \ $$PWD/src/databasemodel.h \ $$PWD/src/sqlgeneratorbase_p.h \ $$PWD/src/postgresqlgenerator.h \ @@ -18,14 +17,16 @@ HEADERS += \ $$PWD/src/tablesetbase_p.h \ $$PWD/src/querybase_p.h \ $$PWD/src/mysqlgenerator.h \ - $$PWD/src/sqlitegenerator.h + $$PWD/src/sqlitegenerator.h \ + $$PWD/src/tablemodel.h \ + $$PWD/src/sqlservergenerator.h \ + $$PWD/src/wherephrase.h SOURCES += \ $$PWD/src/database.cpp \ $$PWD/src/table.cpp \ $$PWD/src/tableset.cpp \ $$PWD/src/query.cpp \ - $$PWD/src/tablescheema.cpp \ $$PWD/src/databasemodel.cpp \ $$PWD/src/tablesetbase.cpp \ $$PWD/src/sqlgeneratorbase.cpp \ @@ -33,4 +34,7 @@ SOURCES += \ $$PWD/src/changelogtable.cpp \ $$PWD/src/querybase.cpp \ $$PWD/src/mysqlgenerator.cpp \ - $$PWD/src/sqlitegenerator.cpp + $$PWD/src/sqlitegenerator.cpp \ + $$PWD/src/tablemodel.cpp \ + $$PWD/src/sqlservergenerator.cpp \ + $$PWD/src/wherephrase.cpp diff --git a/src.tar.gz b/src.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..77e0281ebab7432c121be84b4d92e264c75bd581 GIT binary patch literal 16959 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 WaWMb#FaQ3>fBzrKF;Cq9=m7wfh1?ea literal 0 HcmV?d00001 diff --git a/src/changelogtable.cpp b/src/changelogtable.cpp index fe34e0c..1e8f9d2 100644 --- a/src/changelogtable.cpp +++ b/src/changelogtable.cpp @@ -25,6 +25,7 @@ QT_BEGIN_NAMESPACE ChangeLogTable::ChangeLogTable() { + } QT_END_NAMESPACE diff --git a/src/changelogtable.h b/src/changelogtable.h index 76bddaf..403418d 100644 --- a/src/changelogtable.h +++ b/src/changelogtable.h @@ -33,7 +33,7 @@ class ChangeLogTable : public Table NUT_PRIMARY_AUTO_INCREMENT(id) NUT_DECLARE_FIELD(int, id, id, setId) - NUT_DECLARE_FIELD(QByteArray, data, data, setData) + NUT_DECLARE_FIELD(QString, data, data, setData) NUT_DECLARE_FIELD(int, versionMajor, versionMajor, setVersionMajor) diff --git a/src/database.cpp b/src/database.cpp index 8131b82..c443093 100644 --- a/src/database.cpp +++ b/src/database.cpp @@ -33,10 +33,11 @@ #include "tableset.h" #include "database_p.h" #include "defines_p.h" -#include "tablescheema.h" +#include "tablemodel.h" #include "postgresqlgenerator.h" #include "mysqlgenerator.h" #include "sqlitegenerator.h" +#include "sqlservergenerator.h" #include "query.h" #include @@ -63,13 +64,18 @@ bool DatabasePrivate::open() qWarning("Could not connect to database"); qWarning(db.lastError().text().toLocal8Bit().data()); - if(db.lastError().text().contains("database \"" + databaseName + "\" does not exist")){ - db.setDatabaseName(""); + if(db.lastError().text().contains("database \"" + databaseName + "\" does not exist") + || db.lastError().text().contains("Cannot open database")){ + db.setDatabaseName(sqlGenertor->masterDatabaseName(databaseName)); ok = db.open(); qInfo("Creating database"); if(ok){ db.exec("CREATE DATABASE " + databaseName); db.close(); + + if(db.lastError().type() != QSqlError::NoError) + qWarning(db.lastError().text().prepend("Creating database error: ").toLatin1().data()); + return open(); }else{ qWarning(db.lastError().text().toLatin1().data()); @@ -84,26 +90,25 @@ bool DatabasePrivate::open() bool DatabasePrivate::updateDatabase() { DatabaseModel last = getLastScheema(); + DatabaseModel current = currentModel; - if(last == currentModel){ + if(last == current){ qInfo("Databse is up-to-date"); return true; } - if(!last.size()){ + if(!last.count()) qInfo("Databse is new"); - createChangeLogs(); - }else{ + else qInfo("Databse is changed"); - } - QStringList sql = sqlGenertor->getDiff(last, currentModel); + QStringList sql = sqlGenertor->diff(last, current); db.transaction(); foreach (QString s, sql){ qDebug() << "going to exec " << s; db.exec(s); - if(db.lastError().type() != QSqlError::NoError) + if(!db.lastError().type() == QSqlError::NoError) qWarning(db.lastError().text().toLatin1().data()); } bool ok = db.commit(); @@ -123,82 +128,94 @@ QVariantMap DatabasePrivate::getCurrectScheema() Q_Q(Database); tables.clear(); + //TODO: change logs must not be in model int changeLogTypeId = qRegisterMetaType(); - currentModel.append(new TableScheema(changeLogTypeId, "__change_logs")); + currentModel.append(new TableModel(changeLogTypeId, "__change_logs")); tables.insert("ChangeLogTable", "__change_logs"); for(int i = 0; i < q->metaObject()->classInfoCount(); i++){ QMetaClassInfo ci = q->metaObject()->classInfo(i); - if(QString(ci.name()).startsWith(__nut_TABLE)) + QString ciName = QString(ci.name()).replace(__nut_NAME_PERFIX, ""); + if(ciName.startsWith(__nut_TABLE)) tables.insert(QString(ci.name()).replace(__nut_NAME_PERFIX, "").split(" ").at(1), ci.value()); + + if(ciName == __nut_DB_VERSION){ + QStringList version = QString(ci.value()).split('.'); + bool ok = false; + if(version.length() == 1){ + currentModel.setVersionMajor(version.at(0).toInt(&ok)); + } else if(version.length() == 2){ + currentModel.setVersionMajor(version.at(0).toInt(&ok)); + currentModel.setVersionMinor(version.at(1).toInt(&ok)); + } + + if(!ok) + qFatal("NUT_DB_VERSION macro accept version in format 'x' or 'x.y' only, and x[,y] must be integer values\n"); + } } QVariantMap databaseVariant; for(int i = 1; i < q->metaObject()->propertyCount(); i++){ QMetaProperty tableProperty = q->metaObject()->property(i); - int typeId = QMetaType::type(tableProperty.typeName()); + uint typeId = QMetaType::type(tableProperty.typeName()); if(tables.values().contains(tableProperty.name()) && typeId >= QVariant::UserType){ - TableScheema *sch = new TableScheema(typeId, tableProperty.name()); + TableModel *sch = new TableModel(typeId, tableProperty.name()); currentModel.append(sch); } } - foreach (TableScheema *sch, currentModel) - foreach (Relation *fk, sch->foregionKeys()) - fk->table = currentModel.scheemaByClass(fk->className); + foreach (TableModel *sch, currentModel) + foreach (RelationModel *fk, sch->foregionKeys()) + fk->table = currentModel.modelByClass(fk->className); + return databaseVariant; } DatabaseModel DatabasePrivate::getLastScheema() { -// ChangeLogTable *changeLog = FROM(_changeLogs) -// ORDERBY_DESC(id) -// FIRST(); + ChangeLogTable *u = changeLogs->createQuery()->orderBy("id", "desc")->first(); - auto u = changeLogs->createQuery()->orderBy("id", "desc")->first(); - -// QSqlQuery q = db.exec("select data from __change_logs order by id desc limit 1"); DatabaseModel ret; if(u){ - QJsonObject json = QJsonDocument::fromJson(u->data()).object(); + QJsonObject json = QJsonDocument::fromJson(QByteArray(u->data().toLocal8Bit().data())).object(); foreach (QString key, json.keys()) { - TableScheema *sch = new TableScheema(json.value(key).toObject(), key); + TableModel *sch = new TableModel(json.value(key).toObject(), key); ret.append(sch); } + + u->deleteLater(); } return ret; } bool DatabasePrivate::storeScheemaInDB() { - /*int changeLogTypeId = qRegisterMetaType(); - TableScheema *changeLogModel = new TableScheema(changeLogTypeId, "__change_logs"); - - sqlGenertor->getDiff(0, changeLogModel);*/ - - /*Q_Q(Database); + Q_Q(Database); ChangeLogTable *changeLog = new ChangeLogTable(); changeLog->setData(QJsonDocument(currentModel.toJson()).toJson()); - q->saveChanges();*/ + changeLog->setVersionMajor(currentModel.versionMajor()); + changeLog->setVersionMinor(currentModel.versionMinor()); + changeLogs->append(changeLog); + q->saveChanges(); + changeLog->deleteLater(); - QSqlQuery q(db); - q.prepare("insert into __change_logs (data) values (:data)"); - q.bindValue(":data", QString(QJsonDocument(currentModel.toJson()).toJson())); - bool ret = q.exec(); - if(q.lastError().type() != QSqlError::NoError) - qWarning(q.lastError().text().toLatin1().data()); - return ret; + return true; +// QSqlQuery q(db); +// q.prepare("insert into __change_logs (data) values (:data)"); +// q.bindValue(":data", QString(QJsonDocument(currentModel.toJson()).toJson())); +// bool ret = q.exec(); +// if(q.lastError().type() != QSqlError::NoError) +// qWarning(QString("storeScheemaInDB" + q.lastError().text()).toLatin1().data()); +// return ret; } void DatabasePrivate::createChangeLogs() { - Q_Q(Database); - - QString diff = sqlGenertor->getDiff(0, currentModel.scheema("__change_logs")); + QString diff = sqlGenertor->diff(0, currentModel.model("__change_logs")); db.exec(diff); } @@ -315,12 +332,22 @@ bool Database::open() { Q_D(Database); - if(driver() == "QPSQL") + if(d->driver == "QPSQL" || d->driver == "QPSQL7") d->sqlGenertor = new PostgreSqlGenerator; - else if (driver() == "QMYSQL") + else if (d->driver == "QMYSQL" || d->driver == "QMYSQL3") d->sqlGenertor = new MySqlGenerator; - else if (driver() == "QSQLITE") + else if (d->driver == "QSQLITE" || d->driver == "QSQLITE3") d->sqlGenertor = new SqliteGenerator; + else if(d->driver == "QODBC" || d->driver == "QODBC3"){ + QString driverName = QString::null; + QStringList parts = d->databaseName.toLower().split(';'); + foreach (QString p, parts) + if(p.trimmed().startsWith("driver=")) + driverName = p.split('=').at(1); + + if(driverName == "{sql server}") + d->sqlGenertor = new SqlServerGenerator; + } if(!d->sqlGenertor){ qWarning(QString("Sql generator for driver " + driver() + " not found").toLatin1().data()); @@ -330,23 +357,6 @@ bool Database::open() } } -QString Database::decodeQuery(QString sql) -{ - Q_D(Database); - - sql = sql - .replace("::", ".") - .replace("()", "") - .replace("==", "=") - .replace("!=", "<>"); - - foreach (QString tableName, d->tables.keys()) - sql = sql.replace(tableName + ".", d->tables[tableName] + "."); - - - return sql; -} - QSqlQuery Database::exec(QString sql) { Q_D(Database); @@ -363,10 +373,14 @@ void Database::add(TableSetBase *t) void Database::saveChanges() { - Q_D(Database); - foreach(TableSetBase *ts, tableSets) ts->save(this); } +void Database::cleanUp() +{ + foreach(TableSetBase *ts, tableSets) + ts->clearChilds(); +} + QT_END_NAMESPACE diff --git a/src/database.h b/src/database.h index 94e2251..91896da 100644 --- a/src/database.h +++ b/src/database.h @@ -46,12 +46,11 @@ public: bool open(); - QString decodeQuery(QString sql); - QSqlQuery exec(QString sql); void add(TableSetBase *); void saveChanges(); + void cleanUp(); QString databaseName() const; QString hostName() const; diff --git a/src/databasemodel.cpp b/src/databasemodel.cpp index 83dea77..738d6b1 100644 --- a/src/databasemodel.cpp +++ b/src/databasemodel.cpp @@ -19,29 +19,31 @@ **************************************************************************/ #include "databasemodel.h" -#include "tablescheema.h" +#include "tablemodel.h" #include -DatabaseModel::DatabaseModel() : QList() +QT_BEGIN_NAMESPACE + +DatabaseModel::DatabaseModel() : QList(), _versionMajor(0), _versionMinor(0) { } -TableScheema *DatabaseModel::scheema(QString tableName) const +TableModel *DatabaseModel::model(QString tableName) const { for(int i = 0; i < size(); i++){ - TableScheema *s = at(i); + TableModel *s = at(i); if(s->name() == tableName) return s; } return 0; } -TableScheema *DatabaseModel::scheemaByClass(QString className) const +TableModel *DatabaseModel::modelByClass(QString className) const { for(int i = 0; i < size(); i++){ - TableScheema *s = at(i); + TableModel *s = at(i); if(s->className() == className) return s; } @@ -54,8 +56,8 @@ bool DatabaseModel::operator ==(const DatabaseModel &other) const return false; for(int i = 0; i < size(); i++){ - TableScheema *mine = at(i); - TableScheema *others = other.scheema(mine->name()); + TableModel *mine = at(i); + TableModel *others = other.model(mine->name()); if(!others) return false; @@ -71,36 +73,39 @@ QJsonObject DatabaseModel::toJson() const { QJsonObject obj; +// obj.insert(QT_STRINGIFY(versionMajor), QJsonValue(_versionMajor)); +// obj.insert(QT_STRINGIFY(versionMinor), QJsonValue(_versionMinor)); + for(int i = 0; i < size(); i++){ - TableScheema *s = at(i); + TableModel *s = at(i); obj.insert(s->name(), s->toJson()); } return obj; } -Relation *DatabaseModel::relationByClassNames(QString masterClassName, QString childClassName) +RelationModel *DatabaseModel::relationByClassNames(QString masterClassName, QString childClassName) { - TableScheema *childTable = scheemaByClass(childClassName); + TableModel *childTable = modelByClass(childClassName); if(!childTable) return 0; - foreach (Relation *rel, childTable->foregionKeys()) + foreach (RelationModel *rel, childTable->foregionKeys()) if(rel->className == masterClassName) return rel; return 0; } -Relation *DatabaseModel::relationByTableNames(QString masterTableName, QString childTableName) +RelationModel *DatabaseModel::relationByTableNames(QString masterTableName, QString childTableName) { - TableScheema *childTable = scheema(childTableName); + TableModel *childTable = model(childTableName); if(!childTable) return 0; - foreach (Relation *rel, childTable->foregionKeys()) + foreach (RelationModel *rel, childTable->foregionKeys()) if(rel->table->name() == masterTableName) return rel; @@ -110,9 +115,38 @@ Relation *DatabaseModel::relationByTableNames(QString masterTableName, QString c DatabaseModel DatabaseModel::fromJson(QJsonObject &json) { DatabaseModel model; + +// model.setVersionMajor(json.value(QT_STRINGIFY(versionMajor)).toInt()); +// model.setVersionMinor(json.value(QT_STRINGIFY(versionMinor)).toInt()); + foreach (QString key, json.keys()) { - TableScheema *sch = new TableScheema(json.value(key).toObject(), key); + if(!json.value(key).isObject()) + continue; + + TableModel *sch = new TableModel(json.value(key).toObject(), key); model.append(sch); } return model; } + +int DatabaseModel::versionMajor() const +{ + return _versionMajor; +} + +void DatabaseModel::setVersionMajor(int versionMajor) +{ + _versionMajor = versionMajor; +} + +int DatabaseModel::versionMinor() const +{ + return _versionMinor; +} + +void DatabaseModel::setVersionMinor(int versionMinor) +{ + _versionMinor = versionMinor; +} + +QT_END_NAMESPACE diff --git a/src/databasemodel.h b/src/databasemodel.h index 0bc4f8c..dd49512 100644 --- a/src/databasemodel.h +++ b/src/databasemodel.h @@ -23,25 +23,35 @@ #include -class TableScheema; -struct Relation; +QT_BEGIN_NAMESPACE + +class TableModel; +struct RelationModel; class QJsonObject; -class DatabaseModel : public QList +class DatabaseModel : public QList { + int _versionMajor, _versionMinor; public: DatabaseModel(); - TableScheema *scheema(QString tableName) const; - TableScheema *scheemaByClass(QString className) const; + TableModel *model(QString tableName) const; + TableModel *modelByClass(QString className) const; - Relation *relationByClassNames(QString masterClassName, QString childClassName); - Relation *relationByTableNames(QString masterTableName, QString childTableName); + RelationModel *relationByClassNames(QString masterClassName, QString childClassName); + RelationModel *relationByTableNames(QString masterTableName, QString childTableName); bool operator ==(const DatabaseModel &other) const; static DatabaseModel fromJson(QJsonObject &json); QJsonObject toJson() const; + int versionMajor() const; + void setVersionMajor(int versionMajor); + + int versionMinor() const; + void setVersionMinor(int versionMinor); }; +QT_END_NAMESPACE + #endif // DATABASEMODEL_H diff --git a/src/defines.h b/src/defines.h index 07e1903..a48a105 100644 --- a/src/defines.h +++ b/src/defines.h @@ -21,7 +21,7 @@ #ifndef SYNTAX_DEFINES_H #define SYNTAX_DEFINES_H - +#include "qglobal.h" #include "defines_p.h" #define QT_NAMESPACE Nut @@ -33,10 +33,10 @@ #endif // Database -#define NUT_DB_VERSION(major, minor) Q_CLASSINFO(__nut_NAME_PERFIX " " __nut_DB_VERSION, #major "." #minor) +#define NUT_DB_VERSION(major, minor) Q_CLASSINFO(__nut_NAME_PERFIX __nut_DB_VERSION, #major "." #minor) #define NUT_DECLARE_TABLE(type, name) \ - Q_CLASSINFO(__nut_TABLE " " #type, #name) \ + Q_CLASSINFO(__nut_NAME_PERFIX __nut_TABLE " " #type, #name) \ Q_PROPERTY(type* name READ name) \ Q_PROPERTY(TableSet name##s READ name##s) \ type* m_##name; \ @@ -52,7 +52,10 @@ public: \ Q_CLASSINFO(__nut_NAME_PERFIX #name " " __nut_FIELD, #name) \ type m_##name; \ public: \ - static type type_##name; \ + static FieldPhrase name##Field(){ \ + static FieldPhrase f = FieldPhrase(staticMetaObject.className(), #name); \ + return f; \ + } \ type read() const{ \ return m_##name; \ } \ @@ -61,10 +64,10 @@ public: \ propertyChanged(#name); \ } -#define NUT_FOREGION_KEY(type, keytype, name, read, write) \ +#define NUT_FOREGION_KEY(type, keytype, name, read, write) \ Q_PROPERTY(type* name READ read WRITE write) \ - NUT_DECLARE_FIELD(keytype, name##Id, read##Id, write##Id) \ - Q_CLASSINFO(__nut_NAME_PERFIX #name "Id " __nut_FOREGION_KEY, #type) \ + NUT_DECLARE_FIELD(keytype, name##Id, read##Id, write##Id) \ + Q_CLASSINFO(__nut_NAME_PERFIX #name "Id " __nut_FOREGION_KEY, #type) \ type *m_##name; \ public: \ type *read() const { return m_##name ; } \ @@ -72,10 +75,14 @@ public: \ m_##name = name; \ } -#define NUT_DECLARE_CHILD_TABLE(type, n) \ +#define NUT_DECLARE_CHILD_TABLE(type, n) \ private: \ TableSet *m_##n; \ public: \ + /*static type ## Field() const{ \ + static type t; \ + return t; \ + }*/ \ TableSet *n(){ \ return m_##n; \ } @@ -86,29 +93,22 @@ public: \ #define NUT_AUTO_INCREMENT(x) Q_CLASSINFO(__nut_NAME_PERFIX #x " " __nut_AUTO_INCREMENT, #x) #define NUT_PRIMARY_AUTO_INCREMENT(x) NUT_PRIMARY_KEY(x) \ NUT_AUTO_INCREMENT(x) +#define NUT_UNIQUE(x) Q_CLASSINFO(__nut_NAME_PERFIX #x " " __nut_UNIQUE, #x) #define NUT_LEN(x, n) Q_CLASSINFO(__nut_NAME_PERFIX #x " " __nut_LEN, #n) #define NUT_DEFAULT_VALUE(x, n) Q_CLASSINFO(__nut_NAME_PERFIX #x " " __nut_DEFAULT_VALUE, #n) #define NUT_NOT_NULL(x) Q_CLASSINFO(__nut_NAME_PERFIX #x " " __nut_NOT_NULL, "1") #ifndef NUT_NO_KEYWORDS -//Query -# define LIKE -# define BETWEEN(min,max) BETWEEN min AND max -# define IS -# ifndef NULL -# define NULL -# endif - # define FROM(x) /*QScopedPointer*/(x->createQuery()) -# define WHERE(x) ->setWhere(#x) -# define BIND(...) ->bindValues(__VA_ARGS__) +# define WHERE(x) ->setWhere(x) # define JOIN(x) ->join(#x) +# define ORDERBY(x) ->orderBy(#x, "ASC"); +# define ORDERBY_DESC(x) ->orderBy(#x, "DESC"); + # define SELECT() ->toList() # define COUNT() ->count() # define DELETE() ->remove() # define FIRST() ->first() -# define ORDERBY(x) ->orderBy(#x, "ASC"); -# define ORDERBY_DESC(x) ->orderBy(#x, "DESC"); #endif // NUT_NO_KEYWORDS #endif // SYNTAX_DEFINES_H diff --git a/src/defines_p.h b/src/defines_p.h index 2560bb2..9a74f26 100644 --- a/src/defines_p.h +++ b/src/defines_p.h @@ -27,9 +27,10 @@ #define __nut_FIELD "field" #define __nut_DB_VERSION "database_version" -#define __nut_NAME_PERFIX "nut_db_key:" +#define __nut_NAME_PERFIX "nut_db_key::" #define __nut_PRIMARY_KEY "primary_key" #define __nut_AUTO_INCREMENT "auto_increment" +#define __nut_UNIQUE "unique" #define __nut_TABLE "table" #define __nut_TABLE_NAME "table_name" diff --git a/src/mysqlgenerator.cpp b/src/mysqlgenerator.cpp index 0e7e21a..d18b132 100644 --- a/src/mysqlgenerator.cpp +++ b/src/mysqlgenerator.cpp @@ -1,16 +1,35 @@ +/************************************************************************** +** +** 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 "mysqlgenerator.h" -#include "tablescheema.h" +#include "tablemodel.h" QT_BEGIN_NAMESPACE -MySqlGenerator::MySqlGenerator() : SqlGeneratorBase() +MySqlGenerator::MySqlGenerator(QObject *parent) : SqlGeneratorBase(parent) { } -QString MySqlGenerator::getColumnDef(Field *field) +QString MySqlGenerator::fieldType(FieldModel *field) { - QString ret = field->name + " "; QString dbType; switch (field->type) { @@ -20,6 +39,17 @@ QString MySqlGenerator::getColumnDef(Field *field) case QVariant::ByteArray: dbType = "blob"; break; + case QVariant::DateTime: + dbType = "datetime"; + break; + + case QVariant::Date: + dbType = "date"; + break; + + case QVariant::Time: + dbType = "time"; + break; case QVariant::Double: dbType = "real"; break; @@ -35,22 +65,11 @@ QString MySqlGenerator::getColumnDef(Field *field) else dbType = "text"; break; - case QVariant::DateTime: - dbType = "datetime"; - break; - - case QVariant::Date: - dbType = "date"; - break; - - case QVariant::Time: - dbType = "time"; - break; default: dbType = ""; } - ret.append(dbType); - return ret; + + return dbType; } QT_END_NAMESPACE diff --git a/src/mysqlgenerator.h b/src/mysqlgenerator.h index 736db1e..a33d35f 100644 --- a/src/mysqlgenerator.h +++ b/src/mysqlgenerator.h @@ -1,3 +1,23 @@ +/************************************************************************** +** +** 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 MYSQLGENERATOR_H #define MYSQLGENERATOR_H @@ -9,9 +29,9 @@ QT_BEGIN_NAMESPACE class MySqlGenerator : public SqlGeneratorBase { public: - MySqlGenerator(); + MySqlGenerator(QObject *parent = 0); - QString getColumnDef(Field *field); + QString fieldType(FieldModel *field); }; diff --git a/src/postgresqlgenerator.cpp b/src/postgresqlgenerator.cpp index ac8302f..42da93f 100644 --- a/src/postgresqlgenerator.cpp +++ b/src/postgresqlgenerator.cpp @@ -1,17 +1,36 @@ +/************************************************************************** +** +** 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 "postgresqlgenerator.h" #include "table.h" -#include "tablescheema.h" +#include "tablemodel.h" QT_BEGIN_NAMESPACE -PostgreSqlGenerator::PostgreSqlGenerator() : SqlGeneratorBase () +PostgreSqlGenerator::PostgreSqlGenerator(QObject *parent) : SqlGeneratorBase (parent) { } -QString PostgreSqlGenerator::getColumnDef(Field *field) +QString PostgreSqlGenerator::fieldType(FieldModel *field) { - QString ret = field->name + " "; QString dbType; switch (field->type) { @@ -27,8 +46,8 @@ QString PostgreSqlGenerator::getColumnDef(Field *field) case QVariant::DateTime: dbType = "timestamp"; break; - case QVariant::Double: - dbType = "real"; + case QVariant::Time: + dbType = "time"; break; case QVariant::Int: if(field->isAutoIncrement) @@ -36,36 +55,42 @@ QString PostgreSqlGenerator::getColumnDef(Field *field) else dbType = "integer"; break; + case QVariant::Double: + dbType = "real"; + break; case QVariant::String: if(field->length) dbType = QString("varchar(%1)").arg(field->length); else dbType = "text"; break; - case QVariant::Time: - dbType = "time"; - break; default: dbType = ""; } - ret.append(dbType); - return ret; + + return dbType; } -//QString PostgreSqlGenerator::saveSql(Table *t, QString tableName) -//{ -// switch(t->status()){ -// case Table::Added: -// return insertCommand(t, tableName) + " RETURNING " + t->primaryKey(); - -// default: -// return SqlGeneratorBase::saveSql(t, tableName); -// } -//} - -QString PostgreSqlGenerator::deleteTableRows(QString tableName, QString where) +QString PostgreSqlGenerator::diff(FieldModel *oldField, FieldModel *newField) { - return SqlGeneratorBase::deleteTableRows(tableName, where) + " RETURNING *"; + QString sql = ""; + if(oldField && newField) + if(*oldField == *newField) + return QString::null; + + if(!newField){ + sql = "DROP COLUMN " + oldField->name; + }else{ + if(oldField){ + sql = "ALTER COLUMN "; + sql.append(newField->name + " TYPE " + fieldType(newField)); + } else { + sql = "ADD COLUMN "; + sql.append(fieldDeclare(newField)); + } + } + return sql; } + QT_END_NAMESPACE diff --git a/src/postgresqlgenerator.h b/src/postgresqlgenerator.h index 976716a..e7181ec 100644 --- a/src/postgresqlgenerator.h +++ b/src/postgresqlgenerator.h @@ -1,3 +1,23 @@ +/************************************************************************** +** +** 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 POSTGRESQLGENERATOR_H #define POSTGRESQLGENERATOR_H @@ -6,16 +26,14 @@ QT_BEGIN_NAMESPACE -class Field; class PostgreSqlGenerator : public SqlGeneratorBase { public: - PostgreSqlGenerator(); + PostgreSqlGenerator(QObject *parent = 0); - QString getColumnDef(Field *field); -// QString saveSql(Table *t, QString tableName); + QString fieldType(FieldModel *field); - QString deleteTableRows(QString tableName, QString where); + QString diff(FieldModel *oldField, FieldModel *newField); }; QT_END_NAMESPACE diff --git a/src/query.h b/src/query.h index e8ab6b0..6e8ed72 100644 --- a/src/query.h +++ b/src/query.h @@ -31,6 +31,7 @@ #include "tablesetbase_p.h" #include "sqlgeneratorbase_p.h" #include "querybase_p.h" +#include "wherephrase.h" QT_BEGIN_NAMESPACE @@ -39,41 +40,48 @@ class NUT_EXPORT Query : public QueryBase { QString _tableName; QString _select; - QString _where; - QString _joinClassName; +// QString _where; Database *_database; TableSetBase *_tableSet; + QString _joinClassName; + QList _wheres; public: Query(Database *database, TableSetBase *tableSet); + Query(TableSet *tset){ + _database = tset->database(); + _tableName = _database->tableName(T::staticMetaObject.className()); + } + QList toList(int count = -1); T *first(); int count(); int remove(); - void bind(QVariant v); - void bind(QString name, QVariant v); - Query *join(const QString &tableName); - Query *setWhere(const QString &where); - Query *bindValues(QVariant v1 = QVariant(), QVariant v2 = QVariant(), QVariant v3 = QVariant(), - QVariant v4 = QVariant(), QVariant v5 = QVariant(), QVariant v6 = QVariant(), - QVariant v7 = QVariant(), QVariant v8 = QVariant(), QVariant v9 = QVariant()); - + Query *setWhere(FieldPhrase where); +// Query *setWhere(const QString &where); Query *orderBy(QString fieldName, QString type); private: static QHash _compiledCommands; QString compileCommand(QString command); QString queryText(); + QHash _orders; }; +//template +//inline Query createQuery(TableSet *tset) +//{ +// return Query(tset); +//} + template QHash Query::_compiledCommands; template -Q_OUTOFLINE_TEMPLATE Query::Query(Database *database, TableSetBase *tableSet) : QueryBase(database), _database(database), _tableSet(tableSet), - _joinClassName(QString::null) +Q_OUTOFLINE_TEMPLATE Query::Query(Database *database, TableSetBase *tableSet) : QueryBase(database), + _database(database), _tableSet(tableSet), _joinClassName(QString::null) { _tableName = _database->tableName(T::staticMetaObject.className()); } @@ -86,17 +94,17 @@ Q_OUTOFLINE_TEMPLATE QList Query::toList(int count) qDebug()<exec(queryText()); - QString pk =_database->model().scheema(_tableName)->primaryKey(); + QString pk =_database->model().model(_tableName)->primaryKey(); QVariant lastPkValue = QVariant(); int childTypeId = 0; T *lastRow = 0; TableSetBase *childTableSet; - QStringList masterFields = _database->model().scheema(_tableName)->fieldsNames(); + QStringList masterFields = _database->model().model(_tableName)->fieldsNames(); QStringList childFields; if(!_joinClassName.isNull()){ - childFields = _database->model().scheemaByClass(_joinClassName)->fieldsNames(); + childFields = _database->model().modelByClass(_joinClassName)->fieldsNames(); QString joinTableName = _database->tableName(_joinClassName); - childTypeId = _database->model().scheema(joinTableName)->typeId(); + childTypeId = _database->model().model(joinTableName)->typeId(); } while (q.next()) { @@ -168,8 +176,8 @@ Q_OUTOFLINE_TEMPLATE int Query::count() template Q_OUTOFLINE_TEMPLATE int Query::remove() { - QString sql = _database->sqlGenertor()->deleteTableRows(_tableName, _where); - sql = compileCommand(sql); + QString sql = _database->sqlGenertor()->deleteRecords(_tableName, queryText()); +// sql = compileCommand(sql); QSqlQuery q = _database->exec(sql); return q.numRowsAffected(); } @@ -182,45 +190,23 @@ Q_OUTOFLINE_TEMPLATE Query *Query::join(const QString &tableName) } template -Q_OUTOFLINE_TEMPLATE Query *Query::setWhere(const QString &where) +Q_OUTOFLINE_TEMPLATE Query *Query::setWhere(FieldPhrase where) { - _where = where; + _wheres.append(where); return this; } -template -Q_OUTOFLINE_TEMPLATE void Query::bind(QVariant v) -{ - _where = _where.arg(v.toString()); -} - -template -Q_OUTOFLINE_TEMPLATE void Query::bind(QString name, QVariant v) -{ - if(!name.startsWith(":")) - name.prepend(":"); - _where = _where.replace(name, v.toString()); -} - -template -Q_OUTOFLINE_TEMPLATE Query *Query::bindValues(QVariant v1, QVariant v2, QVariant v3, QVariant v4, QVariant v5, QVariant v6, QVariant v7, QVariant v8, QVariant v9) -{ - if(v1 != QVariant()) _where = _where.arg(v1.toString()); - if(v2 != QVariant()) _where = _where.arg(v2.toString()); - if(v3 != QVariant()) _where = _where.arg(v3.toString()); - if(v4 != QVariant()) _where = _where.arg(v4.toString()); - if(v5 != QVariant()) _where = _where.arg(v5.toString()); - if(v6 != QVariant()) _where = _where.arg(v6.toString()); - if(v7 != QVariant()) _where = _where.arg(v7.toString()); - if(v8 != QVariant()) _where = _where.arg(v8.toString()); - if(v9 != QVariant()) _where = _where.arg(v9.toString()); - - return this; -} +//template +//Q_OUTOFLINE_TEMPLATE Query *Query::setWhere(const QString &where) +//{ +// _where = where; +// return this; +//} template Q_OUTOFLINE_TEMPLATE Query *Query::orderBy(QString fieldName, QString type) { + _orders.insert(fieldName, type); return this; } @@ -252,21 +238,26 @@ Q_OUTOFLINE_TEMPLATE QString Query::compileCommand(QString command) template Q_OUTOFLINE_TEMPLATE QString Query::queryText() { - QString orderby = ""; - QString q = compileCommand(_where); + QStringList orderby; + QString q = "";//compileCommand(_where); + foreach (FieldPhrase p, _wheres) { + if(q != "") + q.append(" AND "); + q.append(p.command(_database->sqlGenertor())); + } QString t = _tableName; if(!_joinClassName.isNull()){ QString joinTableName = _database->tableName(_joinClassName); - Relation *rel = _database->model().relationByTableNames(_tableName, joinTableName); + RelationModel *rel = _database->model().relationByTableNames(_tableName, joinTableName); if(rel){ - QString pk = _database->model().scheema(_tableName)->primaryKey(); + QString pk = _database->model().model(_tableName)->primaryKey(); t = QString("%1 INNER JOIN %2 ON (%1.%3 = %2.%4)") .arg(_tableName) .arg(joinTableName) .arg(pk) .arg(rel->localColumn); - orderby = " ORDER BY " + _tableName + "." + pk; + orderby.append(_tableName + "." + pk); }else{ qWarning(QString("Relation between table %1 and class %2 (%3) not exists!") .arg(_tableName) @@ -277,11 +268,23 @@ Q_OUTOFLINE_TEMPLATE QString Query::queryText() } } - return QString("SELECT %1 FROM %2 %3%4") + QString orderText = ""; + if(_orders.count()) + foreach (QString o, _orders.keys()) + orderby.append(o + " " + _orders.value(o)); + + if(orderby.count()) + orderText = " ORDER BY " + orderby.join(", "); + + QString command = QString("SELECT %1 FROM %2 %3%4") .arg(_select) .arg(t) .arg(q.isEmpty() ? "" : "WHERE " + q) - .arg(orderby); + .arg(orderText); + + for(int i = 0; i < _database->model().count(); i++) + command = command.replace(_database->model().at(i)->className() + "." , _database->model().at(i)->name() + "."); + return command; } QT_END_NAMESPACE diff --git a/src/querybase_p.h b/src/querybase_p.h index cd0c59b..dc78ffb 100644 --- a/src/querybase_p.h +++ b/src/querybase_p.h @@ -15,4 +15,4 @@ signals: public slots: }; -#endif // QUERYBASE_H \ No newline at end of file +#endif // QUERYBASE_H diff --git a/src/sqlgeneratorbase.cpp b/src/sqlgeneratorbase.cpp index 2d2d895..98cf3b4 100644 --- a/src/sqlgeneratorbase.cpp +++ b/src/sqlgeneratorbase.cpp @@ -1,11 +1,36 @@ +/************************************************************************** +** +** 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 +#include + #include "databasemodel.h" #include "sqlgeneratorbase_p.h" #include "table.h" -#include "tablescheema.h" +#include "tablemodel.h" QT_BEGIN_NAMESPACE -SqlGeneratorBase::SqlGeneratorBase() +SqlGeneratorBase::SqlGeneratorBase(QObject *parent) : QObject(parent) { } @@ -15,47 +40,60 @@ SqlGeneratorBase::~SqlGeneratorBase() } -QString SqlGeneratorBase::saveSql(Table *t, QString tableName) +QString SqlGeneratorBase::masterDatabaseName(QString databaseName) +{ + Q_UNUSED(databaseName); + return ""; +} + +QString SqlGeneratorBase::saveRecord(Table *t, QString tableName) { switch(t->status()){ case Table::Added: - return insertCommand(t, tableName); + return insertRecord(t, tableName); case Table::Deleted: - return deleteCommand(t, tableName); + return deleteRecord(t, tableName); case Table::Modified: - return updateCommand(t, tableName); + return updateRecord(t, tableName); case Table::NewCreated: case Table::FeatchedFromDB: // disable compiler warning - return "***"; + return ""; } + + return ""; } -QStringList SqlGeneratorBase::getDiff(DatabaseModel lastModel, DatabaseModel newModel) +QString SqlGeneratorBase::fieldDeclare(FieldModel *field) +{ + return field->name + " " + fieldType(field); +} + +QStringList SqlGeneratorBase::diff(DatabaseModel lastModel, DatabaseModel newModel) { QStringList ret; QSet tableNames; - foreach (TableScheema *table, lastModel) + foreach (TableModel *table, lastModel) tableNames.insert(table->name()); - foreach (TableScheema *table, newModel) + foreach (TableModel *table, newModel) tableNames.insert(table->name()); foreach (QString tableName, tableNames) { - TableScheema *oldTable = lastModel.scheema(tableName); - TableScheema *newTable = newModel.scheema(tableName); - ret << getDiff(oldTable, newTable); + TableModel *oldTable = lastModel.model(tableName); + TableModel *newTable = newModel.model(tableName); + ret << diff(oldTable, newTable); } return ret; } -QString SqlGeneratorBase::getDiff(Field *oldField, Field *newField) +QString SqlGeneratorBase::diff(FieldModel *oldField, FieldModel *newField) { QString sql = ""; if(oldField && newField) @@ -69,12 +107,12 @@ QString SqlGeneratorBase::getDiff(Field *oldField, Field *newField) sql = "ALTER COLUMN "; else sql = "ADD COLUMN "; - sql.append(getColumnDef(newField)); + sql.append(fieldDeclare(newField)); } return sql; } -QString SqlGeneratorBase::getDiff(TableScheema *oldTable, TableScheema *newTable) +QString SqlGeneratorBase::diff(TableModel *oldTable, TableModel *newTable) { if(oldTable && newTable) if(*oldTable == *newTable) @@ -86,23 +124,23 @@ QString SqlGeneratorBase::getDiff(TableScheema *oldTable, TableScheema *newTable QSet fieldNames; if(oldTable) - foreach (Field *f, oldTable->fields()) + foreach (FieldModel *f, oldTable->fields()) fieldNames.insert(f->name); - foreach (Field *f, newTable->fields()) + foreach (FieldModel *f, newTable->fields()) fieldNames.insert(f->name); QStringList columnSql; foreach (QString fieldName, fieldNames) { - Field *newField = newTable->field(fieldName); + FieldModel *newField = newTable->field(fieldName); if(oldTable){ - Field *oldField = oldTable->field(fieldName); + FieldModel *oldField = oldTable->field(fieldName); - QString buffer = getDiff(oldField, newField); + QString buffer = diff(oldField, newField); if(!buffer.isNull()) columnSql << buffer; }else{ - columnSql << getColumnDef(newField); + columnSql << fieldDeclare(newField); } } QString sql; @@ -124,7 +162,7 @@ QString SqlGeneratorBase::getDiff(TableScheema *oldTable, TableScheema *newTable return sql; } -QString SqlGeneratorBase::insertCommand(Table *t, QString tableName) +QString SqlGeneratorBase::insertRecord(Table *t, QString tableName) { QString sql = ""; QString key = t->primaryKey(); @@ -142,7 +180,7 @@ QString SqlGeneratorBase::insertCommand(Table *t, QString tableName) return sql; } -QString SqlGeneratorBase::updateCommand(Table *t, QString tableName) +QString SqlGeneratorBase::updateRecord(Table *t, QString tableName) { QString sql = ""; QString key = t->primaryKey(); @@ -160,7 +198,7 @@ QString SqlGeneratorBase::updateCommand(Table *t, QString tableName) return sql; } -QString SqlGeneratorBase::deleteCommand(Table *t, QString tableName) +QString SqlGeneratorBase::deleteRecord(Table *t, QString tableName) { return QString("DELETE FROM %1 WHERE %2='%3'") .arg(tableName) @@ -168,7 +206,7 @@ QString SqlGeneratorBase::deleteCommand(Table *t, QString tableName) .arg(t->primaryValue().toString()); } -QString SqlGeneratorBase::deleteTableRows(QString tableName, QString where) +QString SqlGeneratorBase::deleteRecords(QString tableName, QString where) { QString sql = ""; if(where.isEmpty() || where.isNull()) @@ -178,5 +216,38 @@ QString SqlGeneratorBase::deleteTableRows(QString tableName, QString where) return sql; } +QString SqlGeneratorBase::escapeFieldValue(QVariant &field) const +{ + switch (field.type()) { + case QVariant::Int: + case QVariant::Double: + return field.toString(); + break; + + case QVariant::String: + return "'" + field.toString() + "'"; + + case QVariant::DateTime: + return "'" + field.toDateTime().toString(Qt::ISODate) + "'"; + + case QVariant::Date: + return "'" + field.toDate().toString(Qt::ISODate) + "'"; + + case QVariant::Time: + return "'" + field.toTime().toString(Qt::ISODate) + "'"; + + case QVariant::StringList: + case QVariant::List: + return "['" + field.toStringList().join("', '") + "']"; + + case QVariant::Invalid: + qFatal("Invalud field value"); + return ""; + + default: + return ""; + } +} + QT_END_NAMESPACE diff --git a/src/sqlgeneratorbase_p.h b/src/sqlgeneratorbase_p.h index 4a25dfe..f0ff174 100644 --- a/src/sqlgeneratorbase_p.h +++ b/src/sqlgeneratorbase_p.h @@ -1,35 +1,60 @@ +/************************************************************************** +** +** 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 SQLGENERATORBASE_H #define SQLGENERATORBASE_H #include - -#include +#include +#include QT_BEGIN_NAMESPACE class Table; -class Field; +struct FieldModel; class DatabaseModel; -class TableScheema; -class SqlGeneratorBase +class TableModel; +class SqlGeneratorBase : public QObject { public: - SqlGeneratorBase(); + SqlGeneratorBase(QObject *parent = 0); virtual ~SqlGeneratorBase(); - virtual QString saveSql(Table *t, QString tableName); - virtual QString getColumnDef(Field *field) = 0; - virtual QStringList getDiff(DatabaseModel lastModel, DatabaseModel newModel); - virtual QString getDiff(Field *oldField, Field *newField); - virtual QString getDiff(TableScheema *oldTable, TableScheema *newTable); + virtual QString masterDatabaseName(QString databaseName); + + virtual QString fieldType(FieldModel *field) = 0; + virtual QString fieldDeclare(FieldModel *field); + + virtual QStringList diff(DatabaseModel lastModel, DatabaseModel newModel); + virtual QString diff(FieldModel *oldField, FieldModel *newField); + virtual QString diff(TableModel *oldTable, TableModel *newTable); - virtual QString insertCommand(Table *t, QString tableName); - virtual QString updateCommand(Table *t, QString tableName); - virtual QString deleteCommand(Table *t, QString tableName); + virtual QString saveRecord(Table *t, QString tableName); + virtual QString insertRecord(Table *t, QString tableName); + virtual QString updateRecord(Table *t, QString tableName); + virtual QString deleteRecord(Table *t, QString tableName); - virtual QString deleteTableRows(QString tableName, QString where); + virtual QString deleteRecords(QString tableName, QString where); + virtual QString escapeFieldValue(QVariant &field) const; }; QT_END_NAMESPACE diff --git a/src/sqlitegenerator.cpp b/src/sqlitegenerator.cpp index c04032d..e5f7699 100644 --- a/src/sqlitegenerator.cpp +++ b/src/sqlitegenerator.cpp @@ -1,13 +1,33 @@ +/************************************************************************** +** +** 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 "sqlitegenerator.h" #include "table.h" -#include "tablescheema.h" +#include "tablemodel.h" -SqliteGenerator::SqliteGenerator() : SqlGeneratorBase() +SqliteGenerator::SqliteGenerator(QObject *parent) : SqlGeneratorBase(parent) { } -QString SqliteGenerator::getColumnDef(Field *field) +QString SqliteGenerator::fieldType(FieldModel *field) { QString ret = field->name + " "; QString dbType; @@ -25,13 +45,16 @@ QString SqliteGenerator::getColumnDef(Field *field) case QVariant::DateTime: dbType = "datetime"; break; + case QVariant::Time: + dbType = "time"; + break; case QVariant::Double: dbType = "real"; break; case QVariant::Int: -// if(field->isAutoIncrement) -// dbType = "INTEGER PRIMARY KEY"; -// else + if(field->isPrimaryKey) + dbType = "INTEGER PRIMARY KEY"; + else dbType = "integer"; break; case QVariant::String: @@ -40,12 +63,9 @@ QString SqliteGenerator::getColumnDef(Field *field) else dbType = "text"; break; - case QVariant::Time: - dbType = "time"; - break; default: dbType = ""; } - ret.append(dbType); - return ret; + + return dbType; } diff --git a/src/sqlitegenerator.h b/src/sqlitegenerator.h index 7f7842d..59b817c 100644 --- a/src/sqlitegenerator.h +++ b/src/sqlitegenerator.h @@ -1,3 +1,23 @@ +/************************************************************************** +** +** 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 SQLITEGENERATOR_H #define SQLITEGENERATOR_H @@ -7,9 +27,9 @@ class SqliteGenerator : public SqlGeneratorBase { public: - SqliteGenerator(); + SqliteGenerator(QObject *parent = 0); - QString getColumnDef(Field *field); + QString fieldType(FieldModel *field); }; #endif // SQLITEGENERATOR_H diff --git a/src/sqlservergenerator.cpp b/src/sqlservergenerator.cpp index b2829af..40bc608 100644 --- a/src/sqlservergenerator.cpp +++ b/src/sqlservergenerator.cpp @@ -1,6 +1,105 @@ -#include "sqlservergenerator.h" +/************************************************************************** +** +** 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 . +** +**************************************************************************/ -SqlServerGenerator::SqlServerGenerator() +#include "sqlservergenerator.h" +#include "table.h" +#include "tablemodel.h" + +#include + +QT_BEGIN_NAMESPACE + +SqlServerGenerator::SqlServerGenerator(QObject *parent) : SqlGeneratorBase(parent) { } + +QString SqlServerGenerator::masterDatabaseName(QString databaseName) +{ + return databaseName.replace(QRegularExpression("DATABASE\\=(\\w+)", QRegularExpression::CaseInsensitiveOption), "DATABASE="); +} + +QString SqlServerGenerator::fieldType(FieldModel *field) +{ + QString dbType; + + switch (field->type) { + case QVariant::Bool: + dbType = "bit"; + break; + case QVariant::ByteArray: + dbType = "varbinary"; + + if(field->length) + dbType.append(" (" + QString::number(field->length) + ")"); + else + dbType.append(" (MAX)"); + break; + case QVariant::Date: + dbType = "date"; + break; + case QVariant::DateTime: + dbType = "datetime"; + break; + case QVariant::Time: + dbType = "time"; + break; + case QVariant::Double: + dbType = "real"; + break; + case QVariant::Int: + dbType = "int"; + if(field->isAutoIncrement) + dbType += " identity(1,1)"; + break; + case QVariant::String: + if(field->length) + dbType = QString("varchar(%1)").arg(field->length); + else + dbType = "text"; + break; + default: + dbType = ""; + } + + return dbType; +} + +QString SqlServerGenerator::diff(FieldModel *oldField, FieldModel *newField) +{ + QString sql = ""; + if(oldField && newField) + if(*oldField == *newField) + return QString::null; + + if(!newField){ + sql = "DROP COLUMN " + oldField->name; + }else{ + if(oldField) + sql = "MODIFY COLUMN "; + else + sql = "ADD "; + + sql.append(fieldDeclare(newField)); + } + return sql; +} + +QT_END_NAMESPACE diff --git a/src/sqlservergenerator.h b/src/sqlservergenerator.h index 65b3ce5..5d40f71 100644 --- a/src/sqlservergenerator.h +++ b/src/sqlservergenerator.h @@ -1,12 +1,42 @@ +/************************************************************************** +** +** 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 SQLSERVERGENERATOR_H #define SQLSERVERGENERATOR_H #include +#include "sqlgeneratorbase_p.h" -class SqlServerGenerator +QT_BEGIN_NAMESPACE + +class SqlServerGenerator : public SqlGeneratorBase { public: - SqlServerGenerator(); + SqlServerGenerator(QObject *parent = 0); + + QString masterDatabaseName(QString databaseName); + + QString fieldType(FieldModel *field); + QString diff(FieldModel *oldField, FieldModel *newField); }; -#endif // SQLSERVERGENERATOR_H \ No newline at end of file +QT_END_NAMESPACE + +#endif // SQLSERVERGENERATOR_H diff --git a/src/table.cpp b/src/table.cpp index 0325c0f..67e1bcc 100644 --- a/src/table.cpp +++ b/src/table.cpp @@ -39,58 +39,38 @@ void Table::add(TableSetBase *t) QString Table::primaryKey() const { - static QString ret = QString::null; +// static QString ret = QString::null; - if(ret == QString::null){ - for(int i = 0; i < metaObject()->classInfoCount(); i++){ - QMetaClassInfo ci = metaObject()->classInfo(i); - QString ciName = ci.name(); +// if(ret == QString::null){ +// for(int i = 0; i < metaObject()->classInfoCount(); i++){ +// QMetaClassInfo ci = metaObject()->classInfo(i); +// QString ciName = ci.name(); - if(ciName.startsWith(__nut_NAME_PERFIX)) - ciName.remove(__nut_NAME_PERFIX); +// if(ciName.startsWith(__nut_NAME_PERFIX)) +// ciName.remove(__nut_NAME_PERFIX); - if(ciName.contains(" ")){ - QStringList parts = ciName.split(" "); - QString propName = parts.at(1); - if(propName == __nut_PRIMARY_KEY) - ret = parts.at(0); - } - } +// if(ciName.contains(" ")){ +// QStringList parts = ciName.split(" "); +// QString propName = parts.at(1); +// if(propName == __nut_PRIMARY_KEY) +// ret = parts.at(0); +// } +// } - if(ret == QString::null) - ret = ""; - } +// if(ret == QString::null) +// ret = ""; +// } - return ret; +// return ret; + return TableModel::model(metaObject()->className())->primaryKey(); } -QString Table::autoIncrementField() const +bool Table::isPrimaryKeyAutoIncrement() const { - static QString ret = QString::null; - - if(ret == QString::null){ - for(int i = 0; i < metaObject()->classInfoCount(); i++){ - QMetaClassInfo ci = metaObject()->classInfo(i); - QString ciName = ci.name(); - - if(ciName.startsWith(__nut_NAME_PERFIX)) - ciName.remove(__nut_NAME_PERFIX); - - if(ciName.contains(" ")){ - QStringList parts = ciName.split(" "); - QString propName = parts.at(1); - if(propName == __nut_AUTO_INCREMENT) - ret = parts.at(0); - } - } - - if(ret == QString::null) - ret = ""; - } - - return ret; + return TableModel::model(metaObject()->className())->field(primaryKey())->isAutoIncrement; } + QVariant Table::primaryValue() const { return property(primaryKey().toLatin1().data()); @@ -101,7 +81,6 @@ void Table::propertyChanged(QString propName) if(propName == primaryKey()) return; -// qDebug() << "Table::propertyChanged" << metaObject()->className() << propName; _changedProperties.insert(propName); if(_status == FeatchedFromDB) _status = Modified; @@ -118,14 +97,17 @@ QSet Table::changedProperties() const bool Table::setParentTable(Table *master) { QString masterClassName = master->metaObject()->className(); - TableScheema *myModel = TableScheema::findByClassName(metaObject()->className()); + TableModel *myModel = TableModel::findByClassName(metaObject()->className()); - foreach (Relation *r, myModel->foregionKeys()) + foreach (RelationModel *r, myModel->foregionKeys()) if(r->className == masterClassName) { setProperty(QString(r->localColumn).toLatin1().data(), master->primaryValue()); _changedProperties.insert(r->localColumn); + return true; } + + return false; } TableSetBase *Table::tableSet() const @@ -141,11 +123,9 @@ void Table::setTableSet(TableSetBase *parent) void Table::save(Database *db) { - QSqlQuery q = db->exec(db->sqlGenertor()->saveSql(this, db->tableName(metaObject()->className()))); - //if(q.next()) - // setProperty(primaryKey().toLatin1().data(), q.value(0)); + QSqlQuery q = db->exec(db->sqlGenertor()->saveRecord(this, db->tableName(metaObject()->className()))); - if(status() == Added) + if(status() == Added && isPrimaryKeyAutoIncrement()) setProperty(primaryKey().toLatin1().data(), q.lastInsertId()); foreach(TableSetBase *ts, tableSets) diff --git a/src/table.h b/src/table.h index 348d30c..7c49bd2 100644 --- a/src/table.h +++ b/src/table.h @@ -25,9 +25,9 @@ #include #include -#include "tablescheema.h" +#include "tablemodel.h" #include "defines.h" -//#include "tableset.h" +#include "wherephrase.h" QT_BEGIN_NAMESPACE @@ -52,7 +52,7 @@ public: void save(Database *db); QString primaryKey() const; - QString autoIncrementField() const; + bool isPrimaryKeyAutoIncrement() const; QVariant primaryValue() const; Status status() const; void setStatus(const Status &status); @@ -77,14 +77,10 @@ private: QSet tableSets; -// template -// friend class TableSet; template friend class Query; -// friend class Database; }; QT_END_NAMESPACE -#include "tableset.cpp" #endif // TABLE_H diff --git a/src/tablemodel.cpp b/src/tablemodel.cpp index bd0439b..de22f6e 100644 --- a/src/tablemodel.cpp +++ b/src/tablemodel.cpp @@ -25,100 +25,103 @@ #include #include -#include "tablescheema.h" +#include "tablemodel.h" #include "defines_p.h" -QSet TableScheema::_allModels; +QSet TableModel::_allModels; //QMap TableScheema::scheemas; -QString TableScheema::name() const +QString TableModel::name() const { return _name; } -void TableScheema::setName(const QString &name) +void TableModel::setName(const QString &name) { _name = name; } -QString TableScheema::className() const +QString TableModel::className() const { return _className; } -void TableScheema::setClassName(const QString &className) +void TableModel::setClassName(const QString &className) { _className = className; } -int TableScheema::typeId() const +int TableModel::typeId() const { return _typeId; } -void TableScheema::setTypeId(const int &typeId) +void TableModel::setTypeId(const int &typeId) { _typeId = typeId; } -Field *TableScheema::field(QString name) const +FieldModel *TableModel::field(QString name) const { - foreach (Field *f, _fields) + foreach (FieldModel *f, _fields) if(f->name == name) return f; return 0; } -QList TableScheema::fields() const +QList TableModel::fields() const { return _fields; } -QList TableScheema::foregionKeys() const +QList TableModel::foregionKeys() const { return _foregionKeys; } -QStringList TableScheema::fieldsNames() const +QStringList TableModel::fieldsNames() const { QStringList ret; - foreach (Field *f, _fields) + foreach (FieldModel *f, _fields) ret.append(f->name); return ret; } -TableScheema *TableScheema::findByTypeId(int typeId) +TableModel *TableModel::findByTypeId(int typeId) { - foreach (TableScheema *model, _allModels) + foreach (TableModel *model, _allModels) if(model->typeId() == typeId) return model; return 0; } -TableScheema *TableScheema::findByName(QString name) +TableModel *TableModel::findByName(QString name) { - foreach (TableScheema *model, _allModels) + foreach (TableModel *model, _allModels) if(model->name() == name) return model; return 0; } -TableScheema *TableScheema::findByClassName(QString className) +TableModel *TableModel::findByClassName(QString className) { - foreach (TableScheema *model, _allModels) + foreach (TableModel *model, _allModels) if(model->className() == className) return model; return 0; } -bool TableScheema::operator ==(const TableScheema &t) const{ +bool TableModel::operator ==(const TableModel &t) const{ if(_name != t.name()) return false; - foreach (Field *f, _fields) { - Field *tf = t.field(f->name); + if(fields().count() != t.fields().count()) + return false; + + foreach (FieldModel *f, _fields) { + FieldModel *tf = t.field(f->name); if(!tf) return false; @@ -129,12 +132,12 @@ bool TableScheema::operator ==(const TableScheema &t) const{ return true; } -bool TableScheema::operator !=(const TableScheema &t) const +bool TableModel::operator !=(const TableModel &t) const { return !(*this == t); } -TableScheema::TableScheema(int typeId, QString tableName) +TableModel::TableModel(int typeId, QString tableName) { const QMetaObject *tableMetaObject = QMetaType::metaObjectForType(typeId); @@ -153,7 +156,7 @@ TableScheema::TableScheema(int typeId, QString tableName) QString propName = parts.at(1); if(propName == __nut_FIELD){ - Field *f = new Field; + FieldModel *f = new FieldModel; f->name = parts.at(0); _fields.append(f); } @@ -163,13 +166,14 @@ TableScheema::TableScheema(int typeId, QString tableName) for(int j = 1; j < tableMetaObject->propertyCount(); j++){ QMetaProperty fieldProperty = tableMetaObject->property(j); - Field *f = field(fieldProperty.name()); - if(!f) + FieldModel *fieldObj = field(fieldProperty.name()); + foreach (FieldModel *f, _fields) + if(f->name == fieldProperty.name()) + f = fieldObj; + if(!fieldObj) continue; - f->type = fieldProperty.type(); - - _fields.append(f); + fieldObj->type = fieldProperty.type(); } // Browse class infos @@ -185,7 +189,7 @@ TableScheema::TableScheema(int typeId, QString tableName) QString propName = parts.at(1); if(propName == __nut_FOREGION_KEY){ - Relation *fk = new Relation; + RelationModel *fk = new RelationModel; fk->localColumn = parts.at(0); fk->foregionColumn = value; fk->className = value; @@ -197,7 +201,7 @@ TableScheema::TableScheema(int typeId, QString tableName) } - Field *f = field(parts.at(0)); + FieldModel *f = field(parts.at(0)); if(!f) continue; @@ -211,6 +215,8 @@ TableScheema::TableScheema(int typeId, QString tableName) f->isPrimaryKey = true; else if(propName == __nut_AUTO_INCREMENT) f->isAutoIncrement = true; + else if(propName == __nut_UNIQUE) + f->isUnique = true; } } @@ -234,14 +240,14 @@ TableScheema::TableScheema(int typeId, QString tableName) "primary_key": "id" }, */ -TableScheema::TableScheema(QJsonObject json, QString tableName) +TableModel::TableModel(QJsonObject json, QString tableName) { _name = tableName; QJsonObject fields = json.value(__FIELDS).toObject(); foreach (QString key, fields.keys()) { QJsonObject fieldObject = fields.value(key).toObject(); - Field *f = new Field; + FieldModel *f = new FieldModel; f->name = fieldObject.value(__NAME).toString(); f->type = QVariant::nameToType(fieldObject.value(__TYPE).toString().toLatin1().data()); @@ -264,12 +270,12 @@ TableScheema::TableScheema(QJsonObject json, QString tableName) } -QJsonObject TableScheema::toJson() const +QJsonObject TableModel::toJson() const { QJsonObject obj; QJsonObject fieldsObj; - foreach (Field *f, _fields) { + foreach (FieldModel *f, _fields) { QJsonObject fieldObj; fieldObj.insert(__NAME, f->name); fieldObj.insert(__TYPE, QVariant::typeToName(f->type)); @@ -312,27 +318,27 @@ QJsonObject TableScheema::toJson() const // } //} -//TableScheema *TableScheema::scheema(QString className) -//{ -// foreach (TableScheema *s, scheemas) -// if(s->_className == className) -// return s; -// return 0; -//} - -Relation *TableScheema::foregionKey(QString otherTable) const +TableModel *TableModel::model(QString className) { - foreach (Relation *fk, _foregionKeys) + foreach (TableModel *s, _allModels) + if(s->_className == className) + return s; + return 0; +} + +RelationModel *TableModel::foregionKey(QString otherTable) const +{ + foreach (RelationModel *fk, _foregionKeys) if(fk->className == otherTable) return fk; return 0; } -QString TableScheema::toString() const +QString TableModel::toString() const { QStringList sl; - foreach (Field *f, _fields) + foreach (FieldModel *f, _fields) sl.append(f->name + " " + QVariant::typeToName(f->type)); QString ret = QString("%1 (%2)") @@ -341,9 +347,9 @@ QString TableScheema::toString() const return ret; } -QString TableScheema::primaryKey() const +QString TableModel::primaryKey() const { - foreach (Field *f, _fields) + foreach (FieldModel *f, _fields) if(f->isPrimaryKey) return f->name; return QString::null; diff --git a/src/tablemodel.h b/src/tablemodel.h index f1f646b..828ee2f 100644 --- a/src/tablemodel.h +++ b/src/tablemodel.h @@ -24,11 +24,11 @@ #include #include class QJsonObject; -class TableScheema; +class TableModel; -struct Field{ - Field() : name(QString::null), length(0), defaultValue(QString::null), - notNull(false), isPrimaryKey(false), isAutoIncrement(false) +struct FieldModel{ + FieldModel() : name(QString::null), length(0), defaultValue(QString::null), + notNull(false), isPrimaryKey(false), isAutoIncrement(false), isUnique(false) { } @@ -40,8 +40,9 @@ struct Field{ bool notNull; bool isPrimaryKey; bool isAutoIncrement; + bool isUnique; - bool operator ==(const Field &f) const{ + bool operator ==(const FieldModel &f) const{ bool b = name == f.name && type == f.type @@ -52,32 +53,32 @@ struct Field{ return b; } - bool operator !=(const Field &f) const{ + bool operator !=(const FieldModel &f) const{ return !(*this == f); } }; -struct Relation{ +struct RelationModel{ QString className; QString localColumn; - TableScheema *table; + TableModel *table; QString foregionColumn; }; -class TableScheema +class TableModel { public: - TableScheema(int typeId, QString tableName); - TableScheema(QJsonObject json, QString tableName); + TableModel(int typeId, QString tableName); + TableModel(QJsonObject json, QString tableName); QJsonObject toJson() const; // static TableScheema *registerTable(int typeId, QString tableName); // static void createForegionKeys(); -// static TableScheema* scheema(QString className); + static TableModel* model(QString className); - Field *field(QString name) const; - Relation *foregionKey(QString otherTable) const; + FieldModel *field(QString name) const; + RelationModel *foregionKey(QString otherTable) const; QString toString() const; @@ -91,24 +92,24 @@ public: int typeId() const; void setTypeId(const int &typeId); - QList fields() const; - QList foregionKeys() const; + QList fields() const; + QList foregionKeys() const; QStringList fieldsNames() const; - static TableScheema *findByTypeId(int typeId); - static TableScheema *findByName(QString name); - static TableScheema *findByClassName(QString className); + static TableModel *findByTypeId(int typeId); + static TableModel *findByName(QString name); + static TableModel *findByClassName(QString className); - bool operator ==(const TableScheema &t) const; - bool operator !=(const TableScheema &t) const; + bool operator ==(const TableModel &t) const; + bool operator !=(const TableModel &t) const; private: QString _name; QString _className; int _typeId; - QList _fields; - QList _foregionKeys; - static QSet_allModels; + QList _fields; + QList _foregionKeys; + static QSet_allModels; }; #endif // TABLESCHEEMA_H diff --git a/src/tableset.h b/src/tableset.h index 1e67384..d128ef1 100644 --- a/src/tableset.h +++ b/src/tableset.h @@ -47,6 +47,8 @@ public: void remove(T *t); void remove(QList t); + inline T type() const {} + int length() const; T *at(int i) const; const T &operator[](int i) const; @@ -82,19 +84,20 @@ Q_OUTOFLINE_TEMPLATE int TableSet::length() const template Q_OUTOFLINE_TEMPLATE T *TableSet::at(int i) const { - return (T*)_tables.values().at(i); + return (T*)_tablesList.at(i); } template Q_OUTOFLINE_TEMPLATE const T &TableSet::operator[](int i) const { - return _tables.values()[i]; + return _tablesList[i]; } template Q_OUTOFLINE_TEMPLATE void TableSet::append(T *t) { _tables.insert(t); + _tablesList.append(t); // rows.append(t); t->setTableSet(this); if(t->status() != Table::FeatchedFromDB) diff --git a/src/tablesetbase.cpp b/src/tablesetbase.cpp index 09849e1..a9d0c9f 100644 --- a/src/tablesetbase.cpp +++ b/src/tablesetbase.cpp @@ -35,7 +35,7 @@ TableSetBase::TableSetBase(Table *parent) : QObject(parent), _database(0), _tabl void TableSetBase::save(Database *db) { - foreach (Table *t, _tables) { + foreach (Table *t, _tablesList) { if(_table) t->setParentTable(_table); @@ -47,12 +47,31 @@ void TableSetBase::save(Database *db) } } +void TableSetBase::clearChilds() +{ + foreach (Table *t, _tablesList) + delete t; +} + void TableSetBase::add(Table *t) { - _tables.insert(t); + if(!_tables.contains(t)){ + _tables.insert(t); + _tablesList.append(t); + } } QString TableSetBase::childClassName() const { return _childClassName; } + +Database *TableSetBase::database() const +{ + return _database; +} + +void TableSetBase::setDatabase(Database *database) +{ + _database = database; +} diff --git a/src/tablesetbase_p.h b/src/tablesetbase_p.h index 9d47381..088777e 100644 --- a/src/tablesetbase_p.h +++ b/src/tablesetbase_p.h @@ -37,11 +37,16 @@ public: TableSetBase(Table *parent); virtual void save(Database *db); + void clearChilds(); void add(Table* t); QString childClassName() const; + Database *database() const; + void setDatabase(Database *database); + protected: QSet _tables; + QList _tablesList; QString _tableName; Database *_database; Table *_table; diff --git a/src/wherephrase.cpp b/src/wherephrase.cpp index a21312c..be2d8e0 100644 --- a/src/wherephrase.cpp +++ b/src/wherephrase.cpp @@ -1,6 +1,349 @@ +/************************************************************************** +** +** 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 "wherephrase.h" -WherePhrase::WherePhrase() -{ +QT_BEGIN_NAMESPACE +PhraseData::PhraseData(const char *className, const char *s){ + text = QString(className) + "." + s; + type = Field; } + +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){ + //// qDebug() << operator + // delete left; +} + +QString PhraseData::operatorString() const +{ + switch (operatorCond){ + case PhraseData::Equal: + return "="; + case PhraseData::NotEqual: + return "<>"; + case PhraseData::Less: + return "<"; + case PhraseData::Greater: + return ">"; + case PhraseData::LessEqual: + return "<="; + case PhraseData::GreaterEqual: + return ">="; + case PhraseData::Null: + return "IS NULL"; + + case PhraseData::NotNull: + return "IS NOT NULL"; + + case PhraseData::In: + return "IN"; + + case PhraseData::NotIn: + return "NOT IN"; + + case PhraseData::And: + return "AND"; + case PhraseData::Or: + return "OR"; + + case PhraseData::Like: + return "LIKE"; + case PhraseData::NotLike: + return "NOT LIKE"; + + case PhraseData::Add: + return "+"; + case PhraseData::Minus: + return "-"; + case PhraseData::Multiple: + return "*"; + case PhraseData::Divide: + return "/"; + + case PhraseData::Set: + return "="; + + case PhraseData::Append: + return ","; + } + + return QString(""); +} + +QString PhraseData::escapeVariant() const +{ + switch (operand.type()) { + case QVariant::Int: + case QVariant::Double: + return operand.toString(); + break; + + case QVariant::String: + return "'" + operand.toString() + "'"; + + case QVariant::DateTime: + return "'" + operand.toDateTime().toString() + "'"; + + case QVariant::Date: + return "'" + operand.toDate().toString() + "'"; + + case QVariant::Time: + return "'" + operand.toTime().toString() + "'"; + + case QVariant::StringList: + case QVariant::List: + return "['" + operand.toStringList().join("', '") + "']"; + + case QVariant::Invalid: + return ""; + + default: + return ""; + } +} + +QString PhraseData::command(SqlGeneratorBase *generator) const +{ + QString ret = ""; + + switch(type){ + case Field: + ret = text; + break; + + case WithVariant: + ret = left->command(generator) + " " + operatorString() + " " + escapeVariant(); + break; + + case WithOther: + ret = left->command(generator) + " " + operatorString() + " " + right->command(generator); + break; + + case WithoutOperand: + ret = left->command(generator) + " " + operatorString(); + break; + } + + if(operatorCond == PhraseData::And || operatorCond == PhraseData::Or) + ret = "(" + ret + ")"; + + return ret; +} + + +FieldPhrase::FieldPhrase(const char *className, const char *s) : willDeleteData(false) +{ + data = new PhraseData(className, s); + text = QString(className) + "." + s; +} + +FieldPhrase::FieldPhrase(PhraseData *l) : willDeleteData(false) +{ + data = l; +} + +FieldPhrase::FieldPhrase(PhraseData *l, PhraseData::Condition o) : willDeleteData(false) +{ + data = new PhraseData(l, o); +} + + +FieldPhrase::FieldPhrase(PhraseData *l, PhraseData::Condition o, PhraseData *r) : willDeleteData(false) +{ + data = new PhraseData(l, o, r); +} + +FieldPhrase::FieldPhrase(PhraseData *l, PhraseData::Condition o, QVariant r) : willDeleteData(false) +{ + data = new PhraseData(l, o, r); +} + +FieldPhrase::~FieldPhrase() +{ +// if(willDeleteData) +// delete data; +} + + +QString FieldPhrase::command(SqlGeneratorBase *generator) +{ + willDeleteData = true; + return data->command(generator); +} + +void FieldPhrase::deleteData(PhraseData *d) +{ + deleteData(d); + if(d->type == PhraseData::WithOther){ + delete d->left; + delete d->right; + } + if(d->type == PhraseData::WithVariant) + delete d->left; +} + +FieldPhrase FieldPhrase::operator ==(const FieldPhrase &other){ + return FieldPhrase(this->data, PhraseData::Equal, other.data); +} + +FieldPhrase FieldPhrase::operator !=(const FieldPhrase &other){ + return FieldPhrase(this->data, PhraseData::NotEqual, other.data); +} + +FieldPhrase FieldPhrase::operator <(const FieldPhrase &other){ + return FieldPhrase(this->data, PhraseData::Less, other.data); +} + +FieldPhrase FieldPhrase::operator >(const FieldPhrase &other){ + return FieldPhrase(this->data, PhraseData::Greater, other.data); +} + +FieldPhrase FieldPhrase::operator <=(const FieldPhrase &other){ + return FieldPhrase(this->data, PhraseData::LessEqual, other.data); +} + +FieldPhrase FieldPhrase::operator >=(const FieldPhrase &other){ + return FieldPhrase(this->data, PhraseData::GreaterEqual, other.data); +} + +FieldPhrase FieldPhrase::operator =(const FieldPhrase &other) +{ + return FieldPhrase(this->data, PhraseData::Set, other.data); +} + +FieldPhrase FieldPhrase::operator +(const FieldPhrase &other){ + return FieldPhrase(this->data, PhraseData::Add, other.data); +} + +FieldPhrase FieldPhrase::operator -(const FieldPhrase &other){ + return FieldPhrase(this->data, PhraseData::Minus, other.data); +} + +FieldPhrase FieldPhrase::operator *(const FieldPhrase &other){ + return FieldPhrase(this->data, PhraseData::Multiple, other.data); +} + +FieldPhrase FieldPhrase::operator /(const FieldPhrase &other){ + return FieldPhrase(this->data, PhraseData::Divide, other.data); +} + +FieldPhrase FieldPhrase::operator &&(const FieldPhrase &other){ + return FieldPhrase(this->data, PhraseData::And, other.data); +} + +FieldPhrase FieldPhrase::operator ||(const FieldPhrase &other){ + return FieldPhrase(this->data, PhraseData::Or, other.data); +} + +FieldPhrase FieldPhrase::operator &(const FieldPhrase &other) +{ + return FieldPhrase(this->data, PhraseData::Append, other.data); +} + +FieldPhrase FieldPhrase::operator ,(const FieldPhrase &other) +{ + return FieldPhrase(this->data, PhraseData::Append, other.data); +} + +FieldPhrase 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 FieldPhrase(data); +} + +FieldPhrase FieldPhrase::operator ==(const QVariant &other){ + return FieldPhrase(this->data, PhraseData::Equal, other); +} + +FieldPhrase FieldPhrase::operator !=(const QVariant &other){ + return FieldPhrase(this->data, PhraseData::NotEqual, other); +} + +FieldPhrase FieldPhrase::operator <(const QVariant &other){ + return FieldPhrase(this->data, PhraseData::Less, other); +} + +FieldPhrase FieldPhrase::operator >(const QVariant &other){ + qDebug() << "var"; + return FieldPhrase(this->data, PhraseData::Greater, other); +} + +FieldPhrase FieldPhrase::operator <=(const QVariant &other){ + return FieldPhrase(this->data, PhraseData::LessEqual, other); +} + +FieldPhrase FieldPhrase::operator >=(const QVariant &other){ + return FieldPhrase(this->data, PhraseData::GreaterEqual, other); +} + +FieldPhrase FieldPhrase::operator =(const QVariant &other) +{ + return FieldPhrase(this->data, PhraseData::Set, other); +} + +FieldPhrase FieldPhrase::isNull(){ + return FieldPhrase(this->data, PhraseData::Null); +} + +FieldPhrase FieldPhrase::in(QVariantList list) +{ + return FieldPhrase(this->data, PhraseData::In, list); +} + +FieldPhrase FieldPhrase::in(QStringList list) +{ + return FieldPhrase(this->data, PhraseData::In, list); +} + +FieldPhrase FieldPhrase::like(QString pattern) +{ + return FieldPhrase(this->data, PhraseData::Like, pattern); +} + +QT_END_NAMESPACE + + diff --git a/src/wherephrase.h b/src/wherephrase.h index 5a8bed9..36a015c 100644 --- a/src/wherephrase.h +++ b/src/wherephrase.h @@ -1,12 +1,151 @@ -#ifndef WHEREPHRASE_H -#define WHEREPHRASE_H +/************************************************************************** +** +** 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 PHRASE_H +#define PHRASE_H #include -class WherePhrase -{ -public: - WherePhrase(); +#include +#include +#include +#include + + +QT_BEGIN_NAMESPACE + +class SqlGeneratorBase; +struct PhraseData{ + enum Condition + { + Equal = 0, + Less, + LessEqual, + Null, + In, + Like, + + NotEqual = 10, + GreaterEqual, + Greater, + NotNull, + NotIn, + NotLike, + + And = 20, + Or, + + Append, + Set, + + Add, + Minus, + Multiple, + Divide + }; + + 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(); + + QString operatorString() const; + QString escapeVariant() const; + QString command(SqlGeneratorBase *generator) const; }; -#endif // WHEREPHRASE_H \ No newline at end of file +class FieldPhrase{ + PhraseData *data; + bool willDeleteData; +public: + + QString text; + + FieldPhrase(const char *className, const char* s); + + FieldPhrase(PhraseData *l); + FieldPhrase(PhraseData *l, PhraseData::Condition o); + FieldPhrase(PhraseData *l, PhraseData::Condition o, PhraseData *r); + FieldPhrase(PhraseData *l, PhraseData::Condition o, QVariant r); + + ~FieldPhrase(); + + QString command(SqlGeneratorBase *generator); + + void deleteData(PhraseData *d); + + FieldPhrase operator ==(const FieldPhrase &other); + FieldPhrase operator !=(const FieldPhrase &other); + FieldPhrase operator <(const FieldPhrase &other); + FieldPhrase operator >(const FieldPhrase &other); + FieldPhrase operator <=(const FieldPhrase &other); + FieldPhrase operator >=(const FieldPhrase &other); + + FieldPhrase operator =(const FieldPhrase &other); + + FieldPhrase operator +(const FieldPhrase &other); + FieldPhrase operator -(const FieldPhrase &other); + FieldPhrase operator *(const FieldPhrase &other); + FieldPhrase operator /(const FieldPhrase &other); + + FieldPhrase operator &&(const FieldPhrase &other); + FieldPhrase operator ||(const FieldPhrase &other); + + FieldPhrase operator &(const FieldPhrase &other); + + FieldPhrase operator ,(const FieldPhrase &other); + + FieldPhrase operator !(); + + FieldPhrase operator ==(const QVariant &other); + FieldPhrase operator !=(const QVariant &other); + FieldPhrase operator <(const QVariant &other); + FieldPhrase operator >(const QVariant &other); + FieldPhrase operator <=(const QVariant &other); + FieldPhrase operator >=(const QVariant &other); + + FieldPhrase operator =(const QVariant &other); + + FieldPhrase isNull(); + FieldPhrase in(QVariantList list); + FieldPhrase in(QStringList list); + FieldPhrase like(QString pattern); +}; + +QT_END_NAMESPACE + +#endif // PHRASE_H diff --git a/test/.maintest.cpp.kate-swp b/test/.maintest.cpp.kate-swp deleted file mode 100644 index 1f932fa125bf7a35c4b4e147d7449e39ad694c86..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 341 zcmXYr%MOAt5Jkt2a0l8bAP@2J4N^eeNp#PG1&L9kCjP#hGL!V=o=iJa5%JFLw=>PJ zeVMYqcP2Nt?)~YX53}Fwnv00cheIupnTsO+bqEH`t-F#=q4=q};S>%ra$9sp6Je6`xL_;@%uo+_n>w NkDvw>D1ilq{R31b9=HGi diff --git a/test/comment.h b/test/comment.h index 7a81b13..5899fb6 100644 --- a/test/comment.h +++ b/test/comment.h @@ -14,6 +14,7 @@ class Comment : public Table NUT_DECLARE_FIELD(int, id, id, setId) NUT_DECLARE_FIELD(QString, message, message, setMessage) NUT_DECLARE_FIELD(QDateTime, saveDate, saveDate, setSaveDate) + NUT_DECLARE_FIELD(qreal, point, point, setPoint) NUT_FOREGION_KEY(Post, int, post, post, setPost) diff --git a/test/maintest.cpp b/test/maintest.cpp index cbd2be7..526e0d5 100644 --- a/test/maintest.cpp +++ b/test/maintest.cpp @@ -5,7 +5,7 @@ #include "maintest.h" #include "query.h" #include "tableset.h" -#include "tablescheema.h" +#include "tablemodel.h" #include "databasemodel.h" #include "post.h" @@ -18,18 +18,47 @@ MainTest::MainTest(QObject *parent) : QObject(parent) void MainTest::initTestCase() { - qDebug() << "Table type id:" << qRegisterMetaType(); +// qDebug() << "Table type id:" << qRegisterMetaType(); qDebug() << "User type id:" << qRegisterMetaType(); qDebug() << "Comment type id:" << qRegisterMetaType(); qDebug() << "DB type id:" << qRegisterMetaType(); - db.setDriver("QSQLITE"); + //sql server +// db.setDriver("QODBC"); +// db.setHostName("127.0.0.1"); +// db.setDatabaseName("DRIVER={SQL Server};Server=.;Database=Nut;Uid=sa;Port=1433;Pwd=qwe123!@#;WSID=."); +// db.setUserName("sa"); +// db.setPassword("qwe123!@#"); + + QStringList list; + list << "one" << "two" << "three"; + FieldPhrase q = (Post::idField() = 1) + & (Post::saveDateField() = QDateTime::currentDateTime()) + & (Post::saveDateField() < QDateTime::currentDateTime() +// (/*(Post::saveDateField() > Post::idField()) +// && */ +// !Post::saveDateField().isNull() +// && +// !Post::idField().in(list) +// || (Post::idField() == 4) +// && Post::saveDateField() >= QDateTime::currentDateTime() + /*|| Post::saveDateField().isNull()*/); + qDebug() << "Command="<< q.command(0); + QTEST_ASSERT(1==2); + // postgres + db.setDriver("QPSQL"); db.setHostName("127.0.0.1"); - db.setDatabaseName("nutdb"); -// db.setUserName("postgres"); -// db.setPassword("856856"); + db.setDatabaseName("nutdb3"); + db.setUserName("postgres"); + db.setPassword("856856"); + +// mysql +// db.setDriver("QMYSQL"); +// db.setHostName("127.0.0.1"); +// db.setDatabaseName("nutdb"); // db.setUserName("root"); // db.setPassword("onlyonlyi"); + bool ok = db.open(); QTEST_ASSERT(ok); @@ -49,13 +78,14 @@ void MainTest::createPost() { Post *newPost = new Post; newPost->setTitle("post title"); + newPost->setSaveDate(QDateTime::currentDateTime()); db.posts()->append(newPost); for(int i = 0 ; i < 3; i++){ Comment *comment = new Comment; comment->setMessage("comment #" + QString::number(i)); - + comment->setSaveDate(QDateTime::currentDateTime()); newPost->comments()->append(comment); } db.saveChanges(); @@ -68,22 +98,48 @@ void MainTest::createPost() void MainTest::selectPosts() { - auto q = FROM(db.posts()) - JOIN(Comment) - WHERE(Post::id() == %1) - BIND(postId); + q = FROM(db.posts()) + JOIN(Comment) + WHERE(Post::idField() == postId); + auto posts = q->toList(); + post = posts.at(0); + post->setBody(""); + QTEST_ASSERT(posts.length() == 1); QTEST_ASSERT(posts.at(0)->comments()->length() == 3); QTEST_ASSERT(posts.at(0)->title() == "post title"); - qDebug()<comments()->at(0)->message(); QTEST_ASSERT(posts.at(0)->comments()->at(0)->message() == "comment #0"); QTEST_ASSERT(posts.at(0)->comments()->at(1)->message() == "comment #1"); QTEST_ASSERT(posts.at(0)->comments()->at(2)->message() == "comment #2"); + db.cleanUp(); } +void MainTest::testDate() +{ + QDateTime d = QDateTime::currentDateTime(); + QTime t = QTime(d.time().hour(), d.time().minute(), d.time().second()); + d.setTime(t); + + Post *newPost = new Post; + newPost->setTitle("post title"); + newPost->setSaveDate(d); + + db.posts()->append(newPost); + + db.saveChanges(); + + auto q = FROM(db.posts()) + WHERE(Post::idField() == newPost->id()) + FIRST(); + + qDebug() << d << q->saveDate(); + QTEST_ASSERT(q->saveDate() == d); +} + + void MainTest::selectWithInvalidRelation() { auto q = FROM(db.posts()) @@ -94,8 +150,7 @@ void MainTest::selectWithInvalidRelation() void MainTest::modifyPost() { auto q = FROM(db.posts()) - WHERE(Post::id() == %1) - BIND(postId); + WHERE(Post::idField() == postId); Post *post = q->first(); @@ -105,8 +160,8 @@ void MainTest::modifyPost() db.saveChanges(); q = FROM(db.posts()) - WHERE(Post::id() == %1) - BIND(postId); + WHERE(Post::idField() == postId); + post = q->first(); QTEST_ASSERT(post->title() == "new name"); } @@ -114,15 +169,13 @@ void MainTest::modifyPost() void MainTest::deletePost() { auto count = FROM(db.posts()) - WHERE(Post::id() == %1) - BIND(postId) + WHERE(Post::idField() == postId) DELETE(); QTEST_ASSERT(count == 1); count = FROM(db.posts()) - WHERE(Post::id() == %1) - BIND(postId) + WHERE(Post::idField() == postId) COUNT(); QTEST_ASSERT(count == 0); diff --git a/test/maintest.h b/test/maintest.h index f870330..b0daf10 100644 --- a/test/maintest.h +++ b/test/maintest.h @@ -5,12 +5,14 @@ #include #include "weblogdatabase.h" +class Post; class MainTest : public QObject { Q_OBJECT WeblogDatabase db; int postId; - + Post *post; + Query *q; public: explicit MainTest(QObject *parent = 0); @@ -22,6 +24,7 @@ private slots: void dataScheema(); void createPost(); void selectPosts(); + void testDate(); void selectWithInvalidRelation(); void modifyPost(); void deletePost(); diff --git a/test/post.h b/test/post.h index a295abd..7ece87e 100644 --- a/test/post.h +++ b/test/post.h @@ -18,6 +18,8 @@ class Post : public Table NUT_LEN(title, 50) NUT_DECLARE_FIELD(QString, title, title, setTitle) + NUT_DECLARE_FIELD(QDateTime, saveDate, saveDate, setSaveDate) + NUT_DECLARE_FIELD(QString, body, body, setBody) NUT_DECLARE_CHILD_TABLE(Comment, comments) diff --git a/test/weblogdatabase.h b/test/weblogdatabase.h index e059f7d..58eb7c8 100644 --- a/test/weblogdatabase.h +++ b/test/weblogdatabase.h @@ -9,7 +9,7 @@ class WeblogDatabase : public Database { Q_OBJECT - NUT_DB_VERSION(1, 0) + NUT_DB_VERSION(1, 1) NUT_DECLARE_TABLE(Post, post)