readme updated

This commit is contained in:
Hamed Masafi 2017-02-01 13:31:21 +03:30
parent 25cc851565
commit d3d0ae2532
42 changed files with 346 additions and 173 deletions

View File

@ -6,7 +6,7 @@
## Features:
- Easy to use
- Support PosgtreSQL, MySQL, SQLite, Microsoft Sql Server
- Support PosgtreSQL, MySQL, SQLite and Microsoft Sql Server
- Automatically create and update database
- IDE auto complete support, No hard-code nedded
- Table join detect
@ -15,9 +15,8 @@
### Read data from database:
```cpp
autoq = FROM(db.posts())
WHERE(Post::idField() == postId);
auto q = db.posts()->createQuery();
q->setWhere(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
@ -43,9 +42,8 @@ db.saveChanges();
### Modify database data:
```cpp
auto q = FROM(db.posts())
WHERE(Post::idField() == postId);
auto q = db.posts()->createQuery();
q->setWhere(Post::idField() == postId);
Post *post = q->first();
if(post) {

View File

@ -7,6 +7,8 @@ pattern="\.\.\/src\/([a-z]+)\.h\:class\sNUT_EXPORT\s(\w+)"
echo "" > "Nut"
echo "" > "nut.h"
mkdir -p Nut
while read line; do
if [[ $line =~ $pattern ]]; then
header=${BASH_REMATCH[1]}
@ -15,6 +17,9 @@ while read line; do
echo "#include \"../src/$header.h\"" > $class
echo "#include \"../src/$header.h\"" > "$header.h"
#echo "#include \"../src/$header.h\"" > "Nut/$class"
#echo "#include \"../src/$header.h\"" > "Nut/$header.h"
echo "#include \"../src/$header.h\"" >> "Nut"
echo "#include \"../src/$header.h\"" >> "nut.h"
fi

14
nut.pri
View File

@ -3,10 +3,7 @@ QT += core widgets sql
INCLUDEPATH += $$PWD/include
HEADERS += \
$$PWD/src/database.h \
$$PWD/src/table.h \
$$PWD/src/tableset.h \
$$PWD/src/database_p.h \
$$PWD/src/defines_p.h \
$$PWD/src/defines.h \
$$PWD/src/query.h \
@ -21,11 +18,12 @@ HEADERS += \
$$PWD/src/tablemodel.h \
$$PWD/src/sqlservergenerator.h \
$$PWD/src/wherephrase.h \
$$PWD/src/query_p.h
$$PWD/src/query_p.h \
$$PWD/src/table.h \
$$PWD/src/database.h \
$$PWD/src/database_p.h
SOURCES += \
$$PWD/src/database.cpp \
$$PWD/src/table.cpp \
$$PWD/src/tableset.cpp \
$$PWD/src/query.cpp \
$$PWD/src/databasemodel.cpp \
@ -38,4 +36,6 @@ SOURCES += \
$$PWD/src/sqlitegenerator.cpp \
$$PWD/src/tablemodel.cpp \
$$PWD/src/sqlservergenerator.cpp \
$$PWD/src/wherephrase.cpp
$$PWD/src/wherephrase.cpp \
$$PWD/src/table.cpp \
$$PWD/src/database.cpp

View File

@ -20,7 +20,7 @@
#include "changelogtable.h"
QT_BEGIN_NAMESPACE
NUT_BEGIN_NAMESPACE
ChangeLogTable::ChangeLogTable()
{
@ -28,4 +28,4 @@ ChangeLogTable::ChangeLogTable()
}
QT_END_NAMESPACE
NUT_END_NAMESPACE

View File

@ -24,7 +24,7 @@
#include <QtCore/qglobal.h>
#include "table.h"
QT_BEGIN_NAMESPACE
NUT_BEGIN_NAMESPACE
class ChangeLogTable : public Table
{
@ -43,6 +43,6 @@ public:
ChangeLogTable();
};
QT_END_NAMESPACE
NUT_END_NAMESPACE
#endif // CHANGELOGTABLE_H

View File

@ -32,7 +32,7 @@
#include "table.h"
#include "tableset.h"
#include "database_p.h"
#include "defines_p.h"
#include "defines.h"
#include "tablemodel.h"
#include "postgresqlgenerator.h"
#include "mysqlgenerator.h"
@ -43,7 +43,11 @@
#include <iostream>
#include <cstdarg>
QT_BEGIN_NAMESPACE
#define __CHANGE_LOG_TABLE_NAME "__change_logs"
NUT_BEGIN_NAMESPACE
int DatabasePrivate::lastId = 0;
DatabasePrivate::DatabasePrivate(Database *parent) : q_ptr(parent)
{
@ -51,8 +55,11 @@ DatabasePrivate::DatabasePrivate(Database *parent) : q_ptr(parent)
bool DatabasePrivate::open()
{
Q_Q(Database);
getCurrectScheema();
connectionName = q->metaObject()->className() + QString::number(DatabasePrivate::lastId);
db = QSqlDatabase::addDatabase(driver, connectionName);
db.setHostName(hostName);
db.setDatabaseName(databaseName);
@ -61,8 +68,7 @@ bool DatabasePrivate::open()
bool ok = db.open();
if(!ok){
qWarning("Could not connect to database");
qWarning(db.lastError().text().toLocal8Bit().data());
qWarning("Could not connect to database, error = %s", db.lastError().text().toLocal8Bit().data());
if(db.lastError().text().contains("database \"" + databaseName + "\" does not exist")
|| db.lastError().text().contains("Cannot open database")
@ -75,11 +81,11 @@ bool DatabasePrivate::open()
db.close();
if(db.lastError().type() != QSqlError::NoError)
qWarning(db.lastError().text().prepend("Creating database error: ").toLatin1().data());
qWarning("Creating database error: %s", db.lastError().text().toLatin1().data());
return open();
}else{
qWarning(db.lastError().text().toLatin1().data());
qWarning("Unknown error detecting change logs, %s", db.lastError().text().toLatin1().data());
}
}
return false;
@ -108,11 +114,10 @@ bool DatabasePrivate::updateDatabase()
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)
qWarning(db.lastError().text().toLatin1().data());
qWarning("Error executing sql command, %s", db.lastError().text().toLatin1().data());
}
bool ok = db.commit();
@ -132,26 +137,28 @@ bool DatabasePrivate::updateDatabase()
}
}
}else{
qWarning("Unable update database");
qWarning(db.lastError().text().toLatin1().data());
qWarning("Unable update database, error = %s", db.lastError().text().toLatin1().data());
}
return ok;
}
QVariantMap DatabasePrivate::getCurrectScheema()
void DatabasePrivate::getCurrectScheema()
{
Q_Q(Database);
tables.clear();
//TODO: change logs must not be in model
int changeLogTypeId = qRegisterMetaType<ChangeLogTable*>();
currentModel.append(new TableModel(changeLogTypeId, "__change_logs"));
tables.insert("ChangeLogTable", "__change_logs");
currentModel.append(new TableModel(changeLogTypeId, __CHANGE_LOG_TABLE_NAME));
tables.insert(ChangeLogTable::staticMetaObject.className(), __CHANGE_LOG_TABLE_NAME);
changeLogs = new TableSet<ChangeLogTable>(q);
for(int i = 0; i < q->metaObject()->classInfoCount(); i++){
QMetaClassInfo ci = q->metaObject()->classInfo(i);
QString ciName = QString(ci.name()).replace(__nut_NAME_PERFIX, "").replace("\"", "");
if(ciName.startsWith(__nut_TABLE))
tables.insert(ciName.split(" ").at(1), ci.value());
@ -170,11 +177,11 @@ QVariantMap DatabasePrivate::getCurrectScheema()
}
}
QVariantMap databaseVariant;
for(int i = 1; i < q->metaObject()->propertyCount(); i++){
QMetaProperty tableProperty = q->metaObject()->property(i);
int typeId = QMetaType::type(tableProperty.typeName());
qDebug() << tables.values().contains(tableProperty.name()) << typeId;
if(tables.values().contains(tableProperty.name()) && typeId >= QVariant::UserType){
TableModel *sch = new TableModel(typeId, tableProperty.name());
currentModel.append(sch);
@ -184,13 +191,12 @@ QVariantMap DatabasePrivate::getCurrectScheema()
foreach (TableModel *sch, currentModel)
foreach (RelationModel *fk, sch->foregionKeys())
fk->table = currentModel.modelByClass(fk->className);
return databaseVariant;
}
DatabaseModel DatabasePrivate::getLastScheema()
{
Q_Q(Database);
// ChangeLogTable *u = q->_change_logs()->createQuery()->orderBy("id", "desc")->first();
ChangeLogTable *u = changeLogs->createQuery()->orderBy("id", "desc")->first();
DatabaseModel ret;
@ -206,32 +212,51 @@ DatabaseModel DatabasePrivate::getLastScheema()
u->deleteLater();
}
return ret;
// QSqlQuery query = q->exec("select * from __change_logs order by id desc limit 1");
// DatabaseModel ret;
// if(query.next()){
// QJsonObject json = QJsonDocument::fromJson(query.value("data").toByteArray()).object();
// foreach (QString key, json.keys()) {
// TableModel *sch = new TableModel(json.value(key).toObject(), key);
// ret.append(sch);
// }
// }
//qDebug() << "ret=" <<ret;
// return ret;
}
bool DatabasePrivate::storeScheemaInDB()
{
Q_Q(Database);
DatabaseModel current = currentModel;
/*current.remove(__CHANGE_LOG_TABLE_NAME)*/;
ChangeLogTable *changeLog = new ChangeLogTable();
changeLog->setData(QJsonDocument(currentModel.toJson()).toJson());
changeLog->setVersionMajor(currentModel.versionMajor());
changeLog->setVersionMinor(currentModel.versionMinor());
changeLog->setData(QJsonDocument(current.toJson()).toJson());
changeLog->setVersionMajor(current.versionMajor());
changeLog->setVersionMinor(current.versionMinor());
changeLogs->append(changeLog);
q->saveChanges();
changeLog->deleteLater();
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());
// QSqlQuery query(db);
// query.prepare("insert into __change_logs (data) values (:data)");
// query.bindValue(":data", QString(QJsonDocument(currentModel.toJson()).toJson()));
// bool ret = query.exec();
// if(query.lastError().type() != QSqlError::NoError)
// qWarning(QString("storeScheemaInDB" + query.lastError().text()).toLatin1().data());
// return ret;
}
void DatabasePrivate::createChangeLogs()
{
QString diff = sqlGenertor->diff(0, currentModel.model("__change_logs"));
// currentModel.model("change_log")
QString diff = sqlGenertor->diff(0, currentModel.model("__change_log"));
db.exec(diff);
}
@ -245,7 +270,24 @@ void DatabasePrivate::createChangeLogs()
Database::Database(QObject *parent) : QObject(parent), d_ptr(new DatabasePrivate(this))
{
Q_D(Database);
d->changeLogs = new TableSet<ChangeLogTable>(this);
//d->changeLogs->sett
DatabasePrivate::lastId++;
// m__change_logs = new TableSet<ChangeLogTable>(this);
}
Database::Database(const Database &other, QObject *parent) : QObject(parent), d_ptr(new DatabasePrivate(this))
{
Q_D(Database);
DatabasePrivate::lastId++;
setDriver(other.driver());
setHostName(other.hostName());
setDatabaseName(other.databaseName());
setUserName(other.userName());
setPassword(other.password());
// m__change_logs = new TableSet<ChangeLogTable>(this);
}
QString Database::databaseName() const
@ -381,14 +423,15 @@ bool Database::open()
QStringList parts = d->databaseName.toLower().split(';');
foreach (QString p, parts)
if(p.trimmed().startsWith("driver="))
driverName = p.split('=').at(1);
driverName = p.split('=').at(1).toLower().trimmed();
if(driverName == "{sql server}")
d->sqlGenertor = new SqlServerGenerator(this);
//TODO: add ODBC driver for mysql, postgres, ...
}
if(!d->sqlGenertor){
qWarning(QString("Sql generator for driver " + driver() + " not found").toLatin1().data());
qWarning("Sql generator for driver %s not found", driver().toLatin1().constData());
return false;
}else{
return d->open();
@ -404,10 +447,10 @@ void Database::close()
QSqlQuery Database::exec(QString sql)
{
Q_D(Database);
qDebug() <<sql;
QSqlQuery q = d->db.exec(sql);
if(d->db.lastError().type() != QSqlError::NoError)
qWarning(d->db.lastError().text().toLatin1().data());
qWarning("Error executing sql command: %s", d->db.lastError().text().toLatin1().data());
return q;
}
@ -428,4 +471,4 @@ void Database::cleanUp()
ts->clearChilds();
}
QT_END_NAMESPACE
NUT_END_NAMESPACE

View File

@ -18,8 +18,8 @@
**
**************************************************************************/
#ifndef DATABASE_H
#define DATABASE_H
#ifndef NUTDATABASE_H
#define NUTDATABASE_H
#include <QtCore/qglobal.h>
#include <QtCore/QList>
@ -28,21 +28,25 @@
#include "defines.h"
#include "tableset.h"
QT_BEGIN_NAMESPACE
NUT_BEGIN_NAMESPACE
class DatabaseModel;
class DatabasePrivate;
class TableSetBase;
class SqlGeneratorBase;
class ChangeLogTable;
class NUT_EXPORT Database : public QObject
{
Q_OBJECT
// NUT_DECLARE_TABLE(ChangeLogTable, _change_log)
DatabasePrivate *d_ptr;
Q_DECLARE_PRIVATE(Database)
public:
Database(QObject *parent = 0);
Database(const Database &other, QObject *parent = 0);
bool open();
void close();
@ -82,6 +86,6 @@ private:
QSet<TableSetBase*> tableSets;
};
QT_END_NAMESPACE
NUT_END_NAMESPACE
#endif // DATABASE_H
#endif // NUTDATABASE_H

View File

@ -27,7 +27,7 @@
#include <QDebug>
QT_BEGIN_NAMESPACE
NUT_BEGIN_NAMESPACE
class DatabasePrivate
{
@ -44,7 +44,7 @@ public:
void createChangeLogs();
bool storeScheemaInDB();
DatabaseModel getLastScheema();
QVariantMap getCurrectScheema();
void getCurrectScheema();
QSqlDatabase db;
@ -62,8 +62,10 @@ public:
DatabaseModel currentModel;
TableSet<ChangeLogTable> *changeLogs;
static int lastId;
};
QT_END_NAMESPACE
NUT_END_NAMESPACE
#endif // DATABASE_P_H

View File

@ -23,17 +23,23 @@
#include <QJsonObject>
QT_BEGIN_NAMESPACE
NUT_BEGIN_NAMESPACE
DatabaseModel::DatabaseModel() : QList<TableModel*>(), _versionMajor(0), _versionMinor(0)
{
}
DatabaseModel::DatabaseModel(const DatabaseModel &other) : QList<TableModel*>(other), _versionMajor(0), _versionMinor(0)
{
}
TableModel *DatabaseModel::model(QString tableName) const
{
for(int i = 0; i < size(); i++){
TableModel *s = at(i);
if(s->name() == tableName)
return s;
}
@ -149,4 +155,16 @@ void DatabaseModel::setVersionMinor(int versionMinor)
_versionMinor = versionMinor;
}
QT_END_NAMESPACE
bool DatabaseModel::remove(QString tableName)
{
for(int i = 0; i < size(); i++){
TableModel *s = at(i);
if(s->name() == tableName){
removeAt(i);
return true;
}
}
return false;
}
NUT_END_NAMESPACE

View File

@ -22,17 +22,20 @@
#define DATABASEMODEL_H
#include <QtCore/QList>
#include"defines.h"
QT_BEGIN_NAMESPACE
class QJsonObject;
NUT_BEGIN_NAMESPACE
class TableModel;
struct RelationModel;
class QJsonObject;
class DatabaseModel : public QList<TableModel*>
{
int _versionMajor, _versionMinor;
public:
DatabaseModel();
DatabaseModel(const DatabaseModel &other);
TableModel *model(QString tableName) const;
TableModel *modelByClass(QString className) const;
@ -50,8 +53,10 @@ public:
int versionMinor() const;
void setVersionMinor(int versionMinor);
bool remove(QString tableName);
};
QT_END_NAMESPACE
NUT_END_NAMESPACE
#endif // DATABASEMODEL_H

View File

@ -21,10 +21,11 @@
#ifndef SYNTAX_DEFINES_H
#define SYNTAX_DEFINES_H
#include "qglobal.h"
#include "defines_p.h"
#define NUT_NAMESPACE Nut
#include "defines_p.h"
#include "qglobal.h"
#define QT_NAMESPACE Nut
#ifdef NUT_COMPILE_STATIC
# define NUT_EXPORT
@ -32,19 +33,26 @@
# define NUT_EXPORT Q_DECL_EXPORT
#endif
#ifdef NUT_NAMESPACE
# define __NUT_NAMESPACE_PERFIX NUT_NAMESPACE::
#else
# define __NUT_NAMESPACE_PERFIX
#endif
// Database
#define NUT_DB_VERSION(major, minor) Q_CLASSINFO(QT_STRINGIFY(__nut_NAME_PERFIX __nut_DB_VERSION), QT_STRINGIFY(#major "." #minor))
#define NUT_DECLARE_TABLE(type, name) \
Q_CLASSINFO(QT_STRINGIFY(__nut_NAME_PERFIX __nut_TABLE " " #type), #name) \
Q_PROPERTY(type* name READ name) \
Q_PROPERTY(TableSet<type> name##s READ name##s) \
Q_PROPERTY(__NUT_NAMESPACE_PERFIX TableSet<type> name##s READ name##s) \
type* m_##name; \
TableSet<type> *m_##name##s; \
__NUT_NAMESPACE_PERFIX TableSet<type> *m_##name##s; \
public: \
static const type _##name; \
type* name() const{ return m_##name; } \
TableSet<type> *name##s() const { return m_##name##s; }
__NUT_NAMESPACE_PERFIX TableSet<type> *name##s() const { return m_##name##s; }
//Table
#define NUT_DECLARE_FIELD(type, name, read, write) \
@ -52,8 +60,8 @@ public: \
Q_CLASSINFO(QT_STRINGIFY(__nut_NAME_PERFIX #name " " __nut_FIELD), #name) \
type m_##name; \
public: \
static FieldPhrase name##Field(){ \
static FieldPhrase f = FieldPhrase(staticMetaObject.className(), #name); \
static __NUT_NAMESPACE_PERFIX FieldPhrase name##Field(){ \
static __NUT_NAMESPACE_PERFIX FieldPhrase f = __NUT_NAMESPACE_PERFIX FieldPhrase(staticMetaObject.className(), #name); \
return f; \
} \
type read() const{ \
@ -77,13 +85,13 @@ public: \
#define NUT_DECLARE_CHILD_TABLE(type, n) \
private: \
TableSet<type> *m_##n; \
__NUT_NAMESPACE_PERFIX TableSet<type> *m_##n; \
public: \
static type *n##Table(){ \
static type *n##Table(){ \
static type *f = new type(); \
return f; \
return f; \
} \
TableSet<type> *n(){ \
__NUT_NAMESPACE_PERFIX TableSet<type> *n(){ \
return m_##n; \
}

View File

@ -43,4 +43,12 @@
#define __nut_REMOVE "remove"
#define __nut_CHANGE "change"
#ifdef NUT_NAMESPACE
# define NUT_BEGIN_NAMESPACE namespace NUT_NAMESPACE{
# define NUT_END_NAMESPACE }
#else
# define NUT_BEGIN_NAMESPACE
# define NUT_END_NAMESPACE
#endif
#endif // DEFINES_P_H

View File

@ -21,7 +21,7 @@
#include "mysqlgenerator.h"
#include "tablemodel.h"
QT_BEGIN_NAMESPACE
NUT_BEGIN_NAMESPACE
MySqlGenerator::MySqlGenerator(Database *parent) : SqlGeneratorBase(parent)
{
@ -72,4 +72,4 @@ QString MySqlGenerator::fieldType(FieldModel *field)
return dbType;
}
QT_END_NAMESPACE
NUT_END_NAMESPACE

View File

@ -24,7 +24,7 @@
#include <QtCore/qglobal.h>
#include "sqlgeneratorbase_p.h"
QT_BEGIN_NAMESPACE
NUT_BEGIN_NAMESPACE
class MySqlGenerator : public SqlGeneratorBase
{
@ -35,6 +35,6 @@ public:
};
QT_END_NAMESPACE
NUT_END_NAMESPACE
#endif // MYSQLGENERATOR_H

View File

@ -22,7 +22,7 @@
#include "table.h"
#include "tablemodel.h"
QT_BEGIN_NAMESPACE
NUT_BEGIN_NAMESPACE
PostgreSqlGenerator::PostgreSqlGenerator(Database *parent) : SqlGeneratorBase (parent)
{
@ -93,4 +93,4 @@ QString PostgreSqlGenerator::diff(FieldModel *oldField, FieldModel *newField)
}
QT_END_NAMESPACE
NUT_END_NAMESPACE

View File

@ -24,7 +24,7 @@
#include <QtCore/qglobal.h>
#include "sqlgeneratorbase_p.h"
QT_BEGIN_NAMESPACE
NUT_BEGIN_NAMESPACE
class PostgreSqlGenerator : public SqlGeneratorBase
{
@ -36,6 +36,6 @@ public:
QString diff(FieldModel *oldField, FieldModel *newField);
};
QT_END_NAMESPACE
NUT_END_NAMESPACE
#endif // POSTGRESQLGENERATOR_H

View File

@ -20,7 +20,7 @@
#include "query.h"
QT_BEGIN_NAMESPACE
NUT_BEGIN_NAMESPACE
QueryPrivate::QueryPrivate(QueryBase *parent) : q_ptr(parent),
joinClassName(QString::null)
@ -85,4 +85,4 @@ QueryPrivate::QueryPrivate(QueryBase *parent) : q_ptr(parent),
* \endcode
*/
QT_END_NAMESPACE
NUT_END_NAMESPACE

View File

@ -33,8 +33,9 @@
#include "sqlgeneratorbase_p.h"
#include "querybase_p.h"
#include "wherephrase.h"
#include "tablemodel.h"
QT_BEGIN_NAMESPACE
NUT_BEGIN_NAMESPACE
template<class T>
class NUT_EXPORT Query : public QueryBase
@ -44,6 +45,7 @@ class NUT_EXPORT Query : public QueryBase
public:
Query(Database *database, TableSetBase *tableSet);
~Query();
QList<T *> toList(int count = -1);
@ -72,6 +74,11 @@ public:
Query<T> *orderBy(WherePhrase phrase);
};
template <typename T>
inline Query<T> *createQuery(TableSet<T> *tableSet){
}
template<class T>
Q_OUTOFLINE_TEMPLATE Query<T>::Query(Database *database, TableSetBase *tableSet) : QueryBase(database),
d_ptr(new QueryPrivate(this))
@ -80,13 +87,13 @@ Q_OUTOFLINE_TEMPLATE Query<T>::Query(Database *database, TableSetBase *tableSet)
d->database = database;
d->tableSet = tableSet;
d->tableName = d->database->tableName(T::staticMetaObject.className());
d->tableName = TableModel::findByClassName(T::staticMetaObject.className())->name();
//d->database->tableName(T::staticMetaObject.className());
}
template<class T>
Q_OUTOFLINE_TEMPLATE Query<T>::~Query()
{
qDebug() << "Query::~Query()";
Q_D(Query);
delete d;
}
@ -107,7 +114,7 @@ Q_OUTOFLINE_TEMPLATE QList<T *> Query<T>::toList(int count)
d->tableName,
d->joinClassName));
QString pk =d->database->model().model(d->tableName)->primaryKey();
QString pk = d->database->model().model(d->tableName)->primaryKey();
QVariant lastPkValue = QVariant();
int childTypeId = 0;
T *lastRow = 0;
@ -149,7 +156,7 @@ Q_OUTOFLINE_TEMPLATE QList<T *> Query<T>::toList(int count)
foreach (QString field, childFields)
childTable->setProperty(field.toLatin1().data(), q.value(field));
//TODO: set database for table
childTable->setParent(this);
childTable->setParentTable(lastRow);
childTable->setStatus(Table::FeatchedFromDB);
@ -256,6 +263,6 @@ Q_OUTOFLINE_TEMPLATE Query<T> *Query<T>::orderBy(WherePhrase phrase)
return this;
}
QT_END_NAMESPACE
NUT_END_NAMESPACE
#endif // QUERY_H

View File

@ -26,6 +26,8 @@
#include <QList>
#include <QString>
NUT_BEGIN_NAMESPACE
class Database;
class TableSetBase;
//template<class T>
@ -46,4 +48,6 @@ public:
QList<WherePhrase> orderPhrases;
};
NUT_END_NAMESPACE
#endif // QUERY_P_H

View File

@ -1,6 +1,10 @@
#include "querybase_p.h"
NUT_BEGIN_NAMESPACE
QueryBase::QueryBase(QObject *parent) : QObject(parent)
{
}
NUT_END_NAMESPACE

View File

@ -3,6 +3,9 @@
#include <QtCore/QObject>
#include <QtCore/qglobal.h>
#include "defines.h"
NUT_BEGIN_NAMESPACE
class QueryBase : public QObject
{
@ -15,4 +18,6 @@ signals:
public slots:
};
NUT_END_NAMESPACE
#endif // QUERYBASE_H

View File

@ -30,7 +30,7 @@
#include "tablemodel.h"
#include "wherephrase.h"
QT_BEGIN_NAMESPACE
NUT_BEGIN_NAMESPACE
SqlGeneratorBase::SqlGeneratorBase(Database *parent) : QObject((QObject*)parent)
{
@ -305,7 +305,6 @@ QString SqlGeneratorBase::selectCommand(SqlGeneratorBase::AgregateType t, QStrin
for(int i = 0; i < _database->model().count(); i++)
sql = sql.replace(_database->model().at(i)->className() + "." , _database->model().at(i)->name() + ".");
qDebug() << "new sql" << sql;
return sql;
}
@ -328,7 +327,6 @@ QString SqlGeneratorBase::createWhere(QList<WherePhrase> &wheres)
whereText.append(phrase(w.data()));
}
qDebug() << "WHWRE="<< whereText;
// if(whereText != "")
// whereText.prepend(" WHERE ");
@ -358,11 +356,10 @@ QString SqlGeneratorBase::selectCommand(QString selectPhrase, QList<WherePhrase>
.arg(rel->localColumn);
orderby.append(tableName + "." + pk);
}else{
qWarning(QString("Relation between table %1 and class %2 (%3) not exists!")
.arg(tableName)
.arg(joinClassName)
.arg(joinTableName.isNull() ? "NULL" : joinTableName)
.toLatin1().data());
qWarning("Relation between table %s and class %s (%s) not exists!",
qPrintable(tableName),
qPrintable(joinClassName),
qPrintable(joinTableName.isNull() ? "NULL" : joinTableName));
joinClassName = QString::null;
}
}
@ -385,9 +382,7 @@ QString SqlGeneratorBase::selectCommand(QString selectPhrase, QList<WherePhrase>
for(int i = 0; i < _database->model().count(); i++)
command = command.replace(_database->model().at(i)->className() + "." , _database->model().at(i)->name() + ".");
qDebug() << command;
return command;
}
QString SqlGeneratorBase::deleteCommand(QList<WherePhrase> &wheres, QString tableName)
@ -406,6 +401,10 @@ QString SqlGeneratorBase::deleteCommand(QList<WherePhrase> &wheres, QString tabl
QString SqlGeneratorBase::escapeValue(const QVariant &v)const
{
switch (v.type()) {
case QVariant::Bool:
return v.toBool() ? "1" : "0";
break;
case QVariant::Int:
case QVariant::UInt:
case QVariant::ULongLong:
@ -470,7 +469,6 @@ QString SqlGeneratorBase::phrase(const PhraseData *d) const
{
QString ret = "";
qDebug() << "type"<<d->type;
switch(d->type){
case PhraseData::Field:
ret = d->text;
@ -555,4 +553,4 @@ QString SqlGeneratorBase::operatorString(const PhraseData::Condition &cond) cons
}
QT_END_NAMESPACE
NUT_END_NAMESPACE

View File

@ -26,7 +26,7 @@
#include <QtCore/QStringList>
#include "wherephrase.h"
QT_BEGIN_NAMESPACE
NUT_BEGIN_NAMESPACE
class Table;
struct FieldModel;
@ -98,6 +98,6 @@ private:
QString phraseOrder(const PhraseData *d) const;
};
QT_END_NAMESPACE
NUT_END_NAMESPACE
#endif // SQLGENERATORBASE_H

View File

@ -22,6 +22,8 @@
#include "table.h"
#include "tablemodel.h"
NUT_BEGIN_NAMESPACE
SqliteGenerator::SqliteGenerator(Database *parent) : SqlGeneratorBase(parent)
{
@ -69,3 +71,5 @@ QString SqliteGenerator::fieldType(FieldModel *field)
return dbType;
}
NUT_END_NAMESPACE

View File

@ -24,6 +24,8 @@
#include <QtCore/qglobal.h>
#include "sqlgeneratorbase_p.h"
NUT_BEGIN_NAMESPACE
class SqliteGenerator : public SqlGeneratorBase
{
public:
@ -32,4 +34,6 @@ public:
QString fieldType(FieldModel *field);
};
NUT_END_NAMESPACE
#endif // SQLITEGENERATOR_H

View File

@ -24,7 +24,7 @@
#include <QRegularExpression>
QT_BEGIN_NAMESPACE
NUT_BEGIN_NAMESPACE
SqlServerGenerator::SqlServerGenerator(Database *parent) : SqlGeneratorBase(parent)
{
@ -110,4 +110,4 @@ QString SqlServerGenerator::escapeValue(const QVariant &v) const
return SqlGeneratorBase::escapeValue(v);
}
QT_END_NAMESPACE
NUT_END_NAMESPACE

View File

@ -24,7 +24,7 @@
#include <QtCore/qglobal.h>
#include "sqlgeneratorbase_p.h"
QT_BEGIN_NAMESPACE
NUT_BEGIN_NAMESPACE
class SqlServerGenerator : public SqlGeneratorBase
{
@ -39,6 +39,6 @@ public:
QString escapeValue(const QVariant &v) const;
};
QT_END_NAMESPACE
NUT_END_NAMESPACE
#endif // SQLSERVERGENERATOR_H

View File

@ -24,7 +24,7 @@
#include "database.h"
#include "sqlgeneratorbase_p.h"
QT_BEGIN_NAMESPACE
NUT_BEGIN_NAMESPACE
Table::Table(QObject *parent) : QObject(parent)
{
@ -62,12 +62,12 @@ QString Table::primaryKey() const
// }
// return ret;
return TableModel::model(metaObject()->className())->primaryKey();
return TableModel::findByClassName(metaObject()->className())->primaryKey();
}
bool Table::isPrimaryKeyAutoIncrement() const
{
return TableModel::model(metaObject()->className())->field(primaryKey())->isAutoIncrement;
return TableModel::findByClassName(metaObject()->className())->field(primaryKey())->isAutoIncrement;
}
@ -143,4 +143,4 @@ void Table::setStatus(const Status &status)
_status = status;
}
QT_END_NAMESPACE
NUT_END_NAMESPACE

View File

@ -29,7 +29,7 @@
#include "defines.h"
#include "wherephrase.h"
QT_BEGIN_NAMESPACE
NUT_BEGIN_NAMESPACE
class Database;
class TableSetBase;
@ -81,6 +81,6 @@ private:
friend class Query;
};
QT_END_NAMESPACE
NUT_END_NAMESPACE
#endif // TABLE_H

View File

@ -26,8 +26,9 @@
#include <QJsonObject>
#include "tablemodel.h"
#include "defines_p.h"
#include "defines.h"
NUT_BEGIN_NAMESPACE
QSet<TableModel*> TableModel::_allModels;
//QMap<int, TableScheema*> TableScheema::scheemas;
@ -107,9 +108,10 @@ TableModel *TableModel::findByName(QString name)
TableModel *TableModel::findByClassName(QString className)
{
foreach (TableModel *model, _allModels)
foreach (TableModel *model, _allModels){
if(model->className() == className)
return model;
}
return 0;
}
@ -145,6 +147,12 @@ TableModel::TableModel(int typeId, QString tableName)
_name = tableName;
_className = tableMetaObject->className();
qDebug() << "New model"<< _className << tableName;
//#ifdef NUT_NAMESPACE
// if(_className.startsWith(QT_STRINGIFY(NUT_NAMESPACE) "::"))
// _className = _className.replace(QT_STRINGIFY(NUT_NAMESPACE) "::", "");
//#endif
// get fields names
for(int j = 0; j < tableMetaObject->classInfoCount(); j++){
QString name = tableMetaObject->classInfo(j).name();
@ -223,6 +231,7 @@ TableModel::TableModel(int typeId, QString tableName)
}
_allModels.insert(this);
qDebug() << "all models"<<_allModels;
}
/*
@ -269,6 +278,8 @@ TableModel::TableModel(QJsonObject json, QString tableName)
if(json.keys().contains(__nut_PRIMARY_KEY))
field(json.value(__nut_PRIMARY_KEY).toString())->isAutoIncrement = true;
_allModels.insert(this);
}
QJsonObject TableModel::toJson() const
@ -279,7 +290,7 @@ QJsonObject TableModel::toJson() const
foreach (FieldModel *f, _fields) {
QJsonObject fieldObj;
fieldObj.insert(__NAME, f->name);
fieldObj.insert(__TYPE, QVariant::typeToName(f->type));
fieldObj.insert(__TYPE, QString(QVariant::typeToName(f->type)));
if(f->length)
fieldObj.insert(__nut_LEN, f->length);
@ -319,13 +330,20 @@ QJsonObject TableModel::toJson() const
// }
//}
TableModel *TableModel::model(QString className)
{
foreach (TableModel *s, _allModels)
if(s->_className == className)
return s;
return 0;
}
//TableModel *TableModel::model(QString className)
//{
// qFatal("");
//#ifdef NUT_NAMESPACE
// if(className.startsWith(QT_STRINGIFY(NUT_NAMESPACE) "::"))
// className = className.replace(QT_STRINGIFY(NUT_NAMESPACE) "::", "");
//#endif
// foreach (TableModel *s, _allModels)
// if(s->_className == className){
// return s;
// }
// return 0;
//}
RelationModel *TableModel::foregionKey(QString otherTable) const
{
@ -355,3 +373,5 @@ QString TableModel::primaryKey() const
return f->name;
return QString::null;
}
NUT_END_NAMESPACE

View File

@ -23,9 +23,13 @@
#include <QtCore/QVariant>
#include <QDebug>
class QJsonObject;
class TableModel;
#include "defines.h"
class QJsonObject;
NUT_BEGIN_NAMESPACE
class TableModel;
struct FieldModel{
FieldModel() : name(QString::null), length(0), defaultValue(QString::null),
notNull(false), isPrimaryKey(false), isAutoIncrement(false), isUnique(false)
@ -44,7 +48,7 @@ struct FieldModel{
bool operator ==(const FieldModel &f) const{
bool b = name == f.name
bool b = name.toLower() == f.name.toLower()
&& type == f.type
&& length == f.length
&& defaultValue == f.defaultValue
@ -75,7 +79,7 @@ public:
// static TableScheema *registerTable(int typeId, QString tableName);
// static void createForegionKeys();
static TableModel* model(QString className);
// static TableModel* model(QString className);
FieldModel *field(QString name) const;
RelationModel *foregionKey(QString otherTable) const;
@ -112,4 +116,6 @@ private:
static QSet<TableModel*>_allModels;
};
NUT_END_NAMESPACE
#endif // TABLESCHEEMA_H

View File

@ -27,10 +27,10 @@
#include <QtSql/QSqlQuery>
#include "tablesetbase_p.h"
#include "database.h"
//#include "database.h"
#include "table.h"
QT_BEGIN_NAMESPACE
NUT_BEGIN_NAMESPACE
template<class T>
class Query;
@ -125,6 +125,6 @@ Q_OUTOFLINE_TEMPLATE void TableSet<T>::remove(QList<T *> t)
remove(i);
}
QT_END_NAMESPACE
NUT_END_NAMESPACE
#endif // TABLESET_H

View File

@ -23,6 +23,8 @@
#include "tablesetbase_p.h"
#include "databasemodel.h"
NUT_BEGIN_NAMESPACE
TableSetBase::TableSetBase(Database *parent) : QObject(parent), _database(parent), _table(0)
{
parent->add(this);
@ -75,3 +77,5 @@ void TableSetBase::setDatabase(Database *database)
{
_database = database;
}
NUT_END_NAMESPACE

View File

@ -27,6 +27,8 @@
#include "defines.h"
NUT_BEGIN_NAMESPACE
class Table;
class Database;
class TableSetBase : public QObject
@ -53,4 +55,6 @@ protected:
QString _childClassName;
};
NUT_END_NAMESPACE
#endif // TABLESETBASE_H

View File

@ -23,41 +23,42 @@
#include "wherephrase.h"
QT_BEGIN_NAMESPACE
NUT_BEGIN_NAMESPACE
PhraseData::PhraseData(const char *className, const char *s){
text = QString(className) + "." + s;
type = Field;
qDebug() << "(" << this << ")" << "Data type 0";
operatorCond = NotAssign;
// qDebug() << "(" << this << ")" << "Data type 0";
}
PhraseData::PhraseData(PhraseData *l, PhraseData::Condition o) : left(l){
operatorCond = o;
type = WithoutOperand;
qDebug() << "(" << this << ")" << "Data type 1";
// qDebug() << "(" << this << ")" << "Data type 1";
}
PhraseData::PhraseData(PhraseData *l, PhraseData::Condition o, const PhraseData *r) : left(l), right(r){
operatorCond = o;
type = WithOther;
qDebug() << "(" << this << ")" << "Data type 2";
// qDebug() << "(" << this << ")" << "Data type 2";
}
PhraseData::PhraseData(PhraseData *l, PhraseData::Condition o, QVariant r) : left(l), operand(r){
operatorCond = o;
type = WithVariant;
qDebug() << "(" << this << ")" << "Data type 1";
// qDebug() << "(" << this << ")" << "Data type 1";
}
PhraseData::~PhraseData(){
qDebug() << "(" << this << ")" << "Data Deleting..." << type;
// qDebug() << "(" << this << ")" << "Data Deleting..." << type;
if(type == WithOther){
qDebug() << " - Other" << left << right;
// qDebug() << " - Other" << left << right;
delete left;
delete right;
}
if(type == WithVariant){
qDebug() << " - Variant" << left;
// qDebug() << " - Variant" << left;
if(left)
delete left;
}
@ -70,7 +71,7 @@ PhraseData *WherePhrase::data() const
WherePhrase::WherePhrase(const char *className, const char *s)
{
qDebug() << "(" << this << ")" << "class ctor" << className << s;
// qDebug() << "(" << this << ")" << "class ctor" << className << s;
_data = new PhraseData(className, s);
}
@ -78,7 +79,7 @@ WherePhrase::WherePhrase(const WherePhrase &l)
{
_data = l._data;
// l._data = 0;
qDebug() << "(" << this << ")" << "Copy ctor, from" << _data << (&l);
// qDebug() << "(" << this << ")" << "Copy ctor, from" << _data << (&l);
_dataPointer = QSharedPointer<PhraseData>(l._dataPointer);
}
@ -86,7 +87,7 @@ WherePhrase::WherePhrase(WherePhrase *l)
{
_data = l->_data;
qDebug() << "(" << this << ")" << "From pointer" << _data;
// qDebug() << "(" << this << ")" << "From pointer" << _data;
// _dataPointer = QSharedPointer<PhraseData>(_data);
l->_data = 0;
l->_dataPointer.reset(0);
@ -97,7 +98,7 @@ WherePhrase::WherePhrase(WherePhrase *l, PhraseData::Condition o)
_data = new PhraseData(l->_data, o);
// _dataPointer = QSharedPointer<PhraseData>(_data);
l->_data = 0;
qDebug() << "(" << this << ")" << "From cond, " << _data << o;
// qDebug() << "(" << this << ")" << "From cond, " << _data << o;
l->_dataPointer.reset(0);
}
@ -109,7 +110,7 @@ WherePhrase::WherePhrase(WherePhrase *l, PhraseData::Condition o, WherePhrase *r
l->_data = 0;
r->_data = 0;
qDebug() << "(" << this << ")" << "From two pointer" << _data;
// qDebug() << "(" << this << ")" << "From two pointer" << _data;
l->_dataPointer.reset(0);
r->_dataPointer.reset(0);
}
@ -120,13 +121,13 @@ WherePhrase::WherePhrase(WherePhrase *l, PhraseData::Condition o, QVariant r)
// _dataPointer = QSharedPointer<PhraseData>(_data);
l->_data = 0;
qDebug() << "(" << this << ")" << "From variant," << _data << l << r;
// qDebug() << "(" << this << ")" << "From variant," << _data << l << r;
l->_dataPointer.reset(0);
}
WherePhrase::~WherePhrase()
{
qDebug() << "(" << this << ")" << "Dtor" << _data << _dataPointer.data();
// qDebug() << "(" << this << ")" << "Dtor" << _data << _dataPointer.data();
// if(_data){
// delete _data;
// qDebug() << "deleted";
@ -200,7 +201,6 @@ WherePhrase WherePhrase::operator ||(const WherePhrase &other)
WherePhrase WherePhrase::operator &(const WherePhrase &other)
{
qDebug() << "append" << this << (&other);
return WherePhrase(this, PhraseData::Append, (WherePhrase*)&other);
}
@ -246,7 +246,7 @@ WherePhrase WherePhrase::operator >=(const QVariant &other)
FieldPhrase::FieldPhrase(const char *className, const char *s) : WherePhrase(className, s)
{
qDebug() << "(" << this << ")" << "FieldPhrase ctor" << className << s;
// qDebug() << "(" << this << ")" << "FieldPhrase ctor" << className << s;
}
WherePhrase FieldPhrase::operator =(const QVariant &other)
@ -273,6 +273,6 @@ WherePhrase FieldPhrase::like(QString pattern)
return WherePhrase(this, PhraseData::Like, pattern);
}
QT_END_NAMESPACE
NUT_END_NAMESPACE

View File

@ -28,8 +28,9 @@
#include <QDateTime>
#include <QTime>
#include <QSharedPointer>
#include "defines.h"
QT_BEGIN_NAMESPACE
NUT_BEGIN_NAMESPACE
class SqlGeneratorBase;
class PhraseData{
@ -155,6 +156,6 @@ public:
//};
QT_END_NAMESPACE
NUT_END_NAMESPACE
#endif // PHRASE_H

View File

@ -34,10 +34,10 @@ void MainTest::initTestCase()
QTEST_ASSERT(ok);
FROM(db.comments())
DELETE();
FROM(db.posts())
DELETE();
// FROM(db.comments())
// DELETE();
// FROM(db.posts())
// DELETE();
}
void MainTest::dataScheema()
@ -128,6 +128,15 @@ void MainTest::selectPostsWithoutTitle()
QTEST_ASSERT(count == 0);
}
void MainTest::selectComments()
{
auto comments = FROM(post->comments())
SELECT();
qDebug() << "comments count"<<comments.count();
// QTEST_ASSERT(comments.count());
}
void MainTest::testDate()
{
QDateTime d = QDateTime::currentDateTime();
@ -146,7 +155,6 @@ void MainTest::testDate()
WHERE(Post::idField() == newPost->id())
FIRST();
qDebug() << d << q->saveDate();
QTEST_ASSERT(q->saveDate() == d);
}

View File

@ -25,6 +25,7 @@ private slots:
void createPost2();
void selectPosts();
void selectPostsWithoutTitle();
void selectComments();
void testDate();
void selectWithInvalidRelation();
void select10NewstPosts();

View File

@ -5,6 +5,10 @@
#include <QtCore/QDateTime>
#include "table.h"
#ifdef NUT_NAMESPACE
using namespace NUT_NAMESPACE;
#endif
class Post;
class Comment : public Table
{

View File

@ -1,22 +1,22 @@
#ifndef CONSTS_H
#define CONSTS_H
//#define DRIVER "QPSQL"
//#define HOST "127.0.0.1"
//#define DATABASE "nutdb3"
//#define USERNAME "postgres"
//#define PASSWORD "856856"
#define DRIVER "QMYSQL"
#define DRIVER "QPSQL"
#define HOST "127.0.0.1"
#define DATABASE "nutdb"
#define USERNAME "root"
#define PASSWORD "onlyonlyi"
#define DATABASE "nutdb2"
#define USERNAME "postgres"
#define PASSWORD "856856"
// 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!@#");
//#define DRIVER "QMYSQL"
//#define HOST "127.0.0.1"
//#define DATABASE "nutdb"
//#define USERNAME "root"
//#define PASSWORD "onlyonlyi"
//#define DRIVER "QODBC"
//#define HOST "127.0.0.1"
//#define DATABASE "DRIVER={SQL Server};Server=.;Database=Nut2;Uid=sa;Port=1433;Pwd=qwe123!@#;WSID=."
//#define USERNAME "sa"
//#define PASSWORD "qwe123!@#"
#endif // CONSTS_H

View File

@ -7,6 +7,10 @@
#include "comment.h"
#include "databasemodel.h"
#ifdef NUT_NAMESPACE
using namespace NUT_NAMESPACE;
#endif
class Post : public Table
{
Q_OBJECT

View File

@ -3,6 +3,10 @@
#include "database.h"
#ifdef NUT_NAMESPACE
using namespace NUT_NAMESPACE;
#endif
class Post;
class Comment;
class WeblogDatabase : public Database