Read me edited
This commit is contained in:
parent
034203c7d0
commit
f87923ff95
|
|
@ -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<Post*> 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();
|
||||
|
||||
|
|
|
|||
12
nut.pri
12
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
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -25,6 +25,7 @@ QT_BEGIN_NAMESPACE
|
|||
ChangeLogTable::ChangeLogTable()
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
142
src/database.cpp
142
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 <iostream>
|
||||
|
|
@ -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<ChangeLogTable*>();
|
||||
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<ChangeLogTable>();
|
||||
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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -19,29 +19,31 @@
|
|||
**************************************************************************/
|
||||
|
||||
#include "databasemodel.h"
|
||||
#include "tablescheema.h"
|
||||
#include "tablemodel.h"
|
||||
|
||||
#include <QJsonObject>
|
||||
|
||||
DatabaseModel::DatabaseModel() : QList<TableScheema*>()
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
DatabaseModel::DatabaseModel() : QList<TableModel*>(), _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
|
||||
|
|
|
|||
|
|
@ -23,25 +23,35 @@
|
|||
|
||||
#include <QtCore/QList>
|
||||
|
||||
class TableScheema;
|
||||
struct Relation;
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class TableModel;
|
||||
struct RelationModel;
|
||||
class QJsonObject;
|
||||
class DatabaseModel : public QList<TableScheema*>
|
||||
class DatabaseModel : public QList<TableModel*>
|
||||
{
|
||||
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
|
||||
|
|
|
|||
|
|
@ -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<type> 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<type> *m_##n; \
|
||||
public: \
|
||||
/*static type ## Field() const{ \
|
||||
static type t; \
|
||||
return t; \
|
||||
}*/ \
|
||||
TableSet<type> *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<QueryBase*>*/(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
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
||||
|
|
|
|||
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#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
|
||||
|
|
|
|||
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#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);
|
||||
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#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
|
||||
|
|
|
|||
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#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
|
||||
|
|
|
|||
115
src/query.h
115
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<FieldPhrase> _wheres;
|
||||
public:
|
||||
Query(Database *database, TableSetBase *tableSet);
|
||||
|
||||
Query(TableSet<T> *tset){
|
||||
_database = tset->database();
|
||||
_tableName = _database->tableName(T::staticMetaObject.className());
|
||||
}
|
||||
|
||||
QList<T *> toList(int count = -1);
|
||||
T *first();
|
||||
int count();
|
||||
int remove();
|
||||
|
||||
void bind(QVariant v);
|
||||
void bind(QString name, QVariant v);
|
||||
|
||||
Query<T> *join(const QString &tableName);
|
||||
Query<T> *setWhere(const QString &where);
|
||||
Query<T> *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<T> *setWhere(FieldPhrase where);
|
||||
// Query<T> *setWhere(const QString &where);
|
||||
Query<T> *orderBy(QString fieldName, QString type);
|
||||
|
||||
private:
|
||||
static QHash<QString, QString> _compiledCommands;
|
||||
QString compileCommand(QString command);
|
||||
QString queryText();
|
||||
QHash<QString, QString> _orders;
|
||||
};
|
||||
|
||||
//template <typename T>
|
||||
//inline Query<T> createQuery(TableSet<T> *tset)
|
||||
//{
|
||||
// return Query<T>(tset);
|
||||
//}
|
||||
|
||||
template<class T>
|
||||
QHash<QString, QString> Query<T>::_compiledCommands;
|
||||
|
||||
template<class T>
|
||||
Q_OUTOFLINE_TEMPLATE Query<T>::Query(Database *database, TableSetBase *tableSet) : QueryBase(database), _database(database), _tableSet(tableSet),
|
||||
_joinClassName(QString::null)
|
||||
Q_OUTOFLINE_TEMPLATE Query<T>::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<T *> Query<T>::toList(int count)
|
|||
qDebug()<<queryText();
|
||||
QSqlQuery q = _database->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<T>::count()
|
|||
template<class T>
|
||||
Q_OUTOFLINE_TEMPLATE int Query<T>::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<T> *Query<T>::join(const QString &tableName)
|
|||
}
|
||||
|
||||
template<class T>
|
||||
Q_OUTOFLINE_TEMPLATE Query<T> *Query<T>::setWhere(const QString &where)
|
||||
Q_OUTOFLINE_TEMPLATE Query<T> *Query<T>::setWhere(FieldPhrase where)
|
||||
{
|
||||
_where = where;
|
||||
_wheres.append(where);
|
||||
return this;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
Q_OUTOFLINE_TEMPLATE void Query<T>::bind(QVariant v)
|
||||
{
|
||||
_where = _where.arg(v.toString());
|
||||
}
|
||||
|
||||
template<class T>
|
||||
Q_OUTOFLINE_TEMPLATE void Query<T>::bind(QString name, QVariant v)
|
||||
{
|
||||
if(!name.startsWith(":"))
|
||||
name.prepend(":");
|
||||
_where = _where.replace(name, v.toString());
|
||||
}
|
||||
|
||||
template<class T>
|
||||
Q_OUTOFLINE_TEMPLATE Query<T> *Query<T>::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<class T>
|
||||
//Q_OUTOFLINE_TEMPLATE Query<T> *Query<T>::setWhere(const QString &where)
|
||||
//{
|
||||
// _where = where;
|
||||
// return this;
|
||||
//}
|
||||
|
||||
template<class T>
|
||||
Q_OUTOFLINE_TEMPLATE Query<T> *Query<T>::orderBy(QString fieldName, QString type)
|
||||
{
|
||||
_orders.insert(fieldName, type);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
@ -252,21 +238,26 @@ Q_OUTOFLINE_TEMPLATE QString Query<T>::compileCommand(QString command)
|
|||
template<class T>
|
||||
Q_OUTOFLINE_TEMPLATE QString Query<T>::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<T>::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
|
||||
|
|
|
|||
|
|
@ -15,4 +15,4 @@ signals:
|
|||
public slots:
|
||||
};
|
||||
|
||||
#endif // QUERYBASE_H
|
||||
#endif // QUERYBASE_H
|
||||
|
|
|
|||
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#include <QDate>
|
||||
#include <QDateTime>
|
||||
#include <QTime>
|
||||
#include <QVariant>
|
||||
|
||||
#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<QString> 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<QString> 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 "<Invalid>";
|
||||
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef SQLGENERATORBASE_H
|
||||
#define SQLGENERATORBASE_H
|
||||
|
||||
#include <QtCore/qglobal.h>
|
||||
|
||||
#include <QStringList>
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QStringList>
|
||||
|
||||
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
|
||||
|
|
|
|||
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#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
|
||||
|
|
|
|||
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
SqlServerGenerator::SqlServerGenerator()
|
||||
#include "sqlservergenerator.h"
|
||||
#include "table.h"
|
||||
#include "tablemodel.h"
|
||||
|
||||
#include <QRegularExpression>
|
||||
|
||||
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
|
||||
|
|
|
|||
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef SQLSERVERGENERATOR_H
|
||||
#define SQLSERVERGENERATOR_H
|
||||
|
||||
#include <QtCore/qglobal.h>
|
||||
#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
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // SQLSERVERGENERATOR_H
|
||||
|
|
|
|||
|
|
@ -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<QString> 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)
|
||||
|
|
|
|||
10
src/table.h
10
src/table.h
|
|
@ -25,9 +25,9 @@
|
|||
#include <QtCore/qglobal.h>
|
||||
#include <QtCore/QSet>
|
||||
|
||||
#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<TableSetBase*> tableSets;
|
||||
|
||||
// template<class T>
|
||||
// friend class TableSet;
|
||||
template<class T>
|
||||
friend class Query;
|
||||
// friend class Database;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#include "tableset.cpp"
|
||||
#endif // TABLE_H
|
||||
|
|
|
|||
|
|
@ -25,100 +25,103 @@
|
|||
#include <QJsonArray>
|
||||
#include <QJsonObject>
|
||||
|
||||
#include "tablescheema.h"
|
||||
#include "tablemodel.h"
|
||||
#include "defines_p.h"
|
||||
|
||||
|
||||
QSet<TableScheema*> TableScheema::_allModels;
|
||||
QSet<TableModel*> TableModel::_allModels;
|
||||
//QMap<int, TableScheema*> 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<Field *> TableScheema::fields() const
|
||||
QList<FieldModel *> TableModel::fields() const
|
||||
{
|
||||
return _fields;
|
||||
}
|
||||
|
||||
QList<Relation *> TableScheema::foregionKeys() const
|
||||
QList<RelationModel *> 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;
|
||||
|
|
|
|||
|
|
@ -24,11 +24,11 @@
|
|||
#include <QtCore/QVariant>
|
||||
#include <QDebug>
|
||||
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<Field *> fields() const;
|
||||
QList<Relation *> foregionKeys() const;
|
||||
QList<FieldModel *> fields() const;
|
||||
QList<RelationModel *> 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<Field*> _fields;
|
||||
QList<Relation*> _foregionKeys;
|
||||
static QSet<TableScheema*>_allModels;
|
||||
QList<FieldModel*> _fields;
|
||||
QList<RelationModel*> _foregionKeys;
|
||||
static QSet<TableModel*>_allModels;
|
||||
};
|
||||
|
||||
#endif // TABLESCHEEMA_H
|
||||
|
|
|
|||
|
|
@ -47,6 +47,8 @@ public:
|
|||
void remove(T *t);
|
||||
void remove(QList<T*> 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<T>::length() const
|
|||
template<class T>
|
||||
Q_OUTOFLINE_TEMPLATE T *TableSet<T>::at(int i) const
|
||||
{
|
||||
return (T*)_tables.values().at(i);
|
||||
return (T*)_tablesList.at(i);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
Q_OUTOFLINE_TEMPLATE const T &TableSet<T>::operator[](int i) const
|
||||
{
|
||||
return _tables.values()[i];
|
||||
return _tablesList[i];
|
||||
}
|
||||
|
||||
template<class T>
|
||||
Q_OUTOFLINE_TEMPLATE void TableSet<T>::append(T *t)
|
||||
{
|
||||
_tables.insert(t);
|
||||
_tablesList.append(t);
|
||||
// rows.append(t);
|
||||
t->setTableSet(this);
|
||||
if(t->status() != Table::FeatchedFromDB)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<Table*> _tables;
|
||||
QList<Table*> _tablesList;
|
||||
QString _tableName;
|
||||
Database *_database;
|
||||
Table *_table;
|
||||
|
|
|
|||
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#include <QDataStream>
|
||||
#include <QDebug>
|
||||
|
||||
#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("<FAIL>");
|
||||
}
|
||||
|
||||
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 "<FAIL>";
|
||||
|
||||
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
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef PHRASE_H
|
||||
#define PHRASE_H
|
||||
|
||||
#include <QtCore/qglobal.h>
|
||||
|
||||
class WherePhrase
|
||||
{
|
||||
public:
|
||||
WherePhrase();
|
||||
#include <QVariant>
|
||||
#include <QDate>
|
||||
#include <QDateTime>
|
||||
#include <QTime>
|
||||
|
||||
|
||||
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
|
||||
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
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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<Table*>();
|
||||
// qDebug() << "Table type id:" << qRegisterMetaType<Table*>();
|
||||
qDebug() << "User type id:" << qRegisterMetaType<Post*>();
|
||||
qDebug() << "Comment type id:" << qRegisterMetaType<Comment*>();
|
||||
qDebug() << "DB type id:" << qRegisterMetaType<WeblogDatabase*>();
|
||||
|
||||
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()<<posts.at(0)->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);
|
||||
|
|
|
|||
|
|
@ -5,12 +5,14 @@
|
|||
#include <QtCore/qglobal.h>
|
||||
|
||||
#include "weblogdatabase.h"
|
||||
class Post;
|
||||
class MainTest : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
WeblogDatabase db;
|
||||
int postId;
|
||||
|
||||
Post *post;
|
||||
Query<Post> *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();
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue