diff --git a/doc/nut.index b/doc/nut.index
new file mode 100644
index 0000000..deb4f4e
--- /dev/null
+++ b/doc/nut.index
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/doc/nut.qhp b/doc/nut.qhp
new file mode 100644
index 0000000..5d4c609
--- /dev/null
+++ b/doc/nut.qhp
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/nut.qhp.sha1 b/doc/nut.qhp.sha1
new file mode 100644
index 0000000..d04ba34
--- /dev/null
+++ b/doc/nut.qhp.sha1
@@ -0,0 +1 @@
+da39a3ee5e6b4b0d3255bfef95601890afd80709
\ No newline at end of file
diff --git a/include.tar.gz b/include.tar.gz
new file mode 100644
index 0000000..b9d2984
Binary files /dev/null and b/include.tar.gz differ
diff --git a/include/header_copier b/include/header_copier
old mode 100755
new mode 100644
diff --git a/nut.pri b/nut.pri
index 82e7dbe..bd2f947 100644
--- a/nut.pri
+++ b/nut.pri
@@ -20,7 +20,8 @@ HEADERS += \
$$PWD/src/sqlitegenerator.h \
$$PWD/src/tablemodel.h \
$$PWD/src/sqlservergenerator.h \
- $$PWD/src/wherephrase.h
+ $$PWD/src/wherephrase.h \
+ $$PWD/src/query_p.h
SOURCES += \
$$PWD/src/database.cpp \
diff --git a/nut.qdocconf b/nut.qdocconf
new file mode 100644
index 0000000..6134af9
--- /dev/null
+++ b/nut.qdocconf
@@ -0,0 +1,24 @@
+project = Nut
+description = Advanced, Powerful and easy to use ORM for Qt5
+version = 0.1
+
+outputdir = doc
+
+source += src/query.cpp
+headerdirs += src
+sourcedirs += src
+exampledirs = .
+
+
+
+qhp.projects = Nut
+
+qhp.qtestclass.file = nut.qhp
+qhp.qtestclass.namespace = org.kaj.nut.0.1
+qhp.qtestclass.virtualFolder = nut
+qhp.qtestclass.indexTitle = nut
+qhp.qtestclass.indexRoot =
+
+qhp.qtestclass.filterAttributes = nut 0.1 qtrefdoc
+qhp.qtestclass.customFilters.Qt.name = qtestclass 0.1
+qhp.qtestclass.customFilters.Qt.filterAttributes = qtestclass 0.1
\ No newline at end of file
diff --git a/src/database.cpp b/src/database.cpp
index 4139022..75cc7f3 100644
--- a/src/database.cpp
+++ b/src/database.cpp
@@ -65,10 +65,11 @@ bool DatabasePrivate::open()
qWarning(db.lastError().text().toLocal8Bit().data());
if(db.lastError().text().contains("database \"" + databaseName + "\" does not exist")
- || db.lastError().text().contains("Cannot open database")){
+ || db.lastError().text().contains("Cannot open database")
+ || db.lastError().text().contains("Unknown database '" + databaseName + "'")){
db.setDatabaseName(sqlGenertor->masterDatabaseName(databaseName));
ok = db.open();
- qInfo("Creating database");
+ qDebug("Creating database");
if(ok){
db.exec("CREATE DATABASE " + databaseName);
db.close();
@@ -89,18 +90,20 @@ bool DatabasePrivate::open()
bool DatabasePrivate::updateDatabase()
{
+ Q_Q(Database);
+
DatabaseModel last = getLastScheema();
DatabaseModel current = currentModel;
if(last == current){
- qInfo("Databse is up-to-date");
+ qDebug("Databse is up-to-date");
return true;
}
if(!last.count())
- qInfo("Databse is new");
+ qDebug("Databse is new");
else
- qInfo("Databse is changed");
+ qDebug("Databse is changed");
QStringList sql = sqlGenertor->diff(last, current);
db.transaction();
@@ -108,13 +111,26 @@ bool DatabasePrivate::updateDatabase()
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();
if(ok){
storeScheemaInDB();
+
+ q->databaseUpdated(last.versionMajor(), last.versionMinor(), current.versionMajor(), current.versionMinor());
+ QString versionText = QString::number(current.versionMajor()) + "_" + QString::number(current.versionMinor());
+
+ for(int i = 0; i < q->metaObject()->methodCount(); i++){
+ QMetaMethod m = q->metaObject()->method(i);
+ if(m.name() == "update" + versionText){
+ m.invoke(q, Qt::DirectConnection,
+ Q_ARG(int, current.versionMajor()),
+ Q_ARG(int, current.versionMinor()));
+ break;
+ }
+ }
}else{
qWarning("Unable update database");
qWarning(db.lastError().text().toLatin1().data());
@@ -135,12 +151,12 @@ QVariantMap DatabasePrivate::getCurrectScheema()
for(int i = 0; i < q->metaObject()->classInfoCount(); i++){
QMetaClassInfo ci = q->metaObject()->classInfo(i);
- QString ciName = QString(ci.name()).replace(__nut_NAME_PERFIX, "");
+ QString ciName = QString(ci.name()).replace(__nut_NAME_PERFIX, "").replace("\"", "");
if(ciName.startsWith(__nut_TABLE))
- tables.insert(QString(ci.name()).replace(__nut_NAME_PERFIX, "").split(" ").at(1), ci.value());
+ tables.insert(ciName.split(" ").at(1), ci.value());
if(ciName == __nut_DB_VERSION){
- QStringList version = QString(ci.value()).split('.');
+ QStringList version = QString(ci.value()).replace("\"", "").split('.');
bool ok = false;
if(version.length() == 1){
currentModel.setVersionMajor(version.at(0).toInt(&ok));
@@ -150,14 +166,14 @@ QVariantMap DatabasePrivate::getCurrectScheema()
}
if(!ok)
- qFatal("NUT_DB_VERSION macro accept version in format 'x' or 'x.y' only, and x[,y] must be integer values\n");
+ 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);
- uint typeId = QMetaType::type(tableProperty.typeName());
+ int typeId = QMetaType::type(tableProperty.typeName());
if(tables.values().contains(tableProperty.name()) && typeId >= QVariant::UserType){
TableModel *sch = new TableModel(typeId, tableProperty.name());
@@ -220,6 +236,12 @@ void DatabasePrivate::createChangeLogs()
db.exec(diff);
}
+
+/*!
+ * \class Database
+ * \brief Database class
+ */
+
Database::Database(QObject *parent) : QObject(parent), d_ptr(new DatabasePrivate(this))
{
Q_D(Database);
@@ -268,6 +290,10 @@ QString Database::driver() const
return d->driver;
}
+/*!
+ * \brief Database::model
+ * \return The model of this database
+ */
DatabaseModel Database::model() const
{
Q_D(const Database);
@@ -328,6 +354,14 @@ SqlGeneratorBase *Database::sqlGenertor() const
return d->sqlGenertor;
}
+void Database::databaseUpdated(int oldMajor, int oldMinor, int newMajor, int newMinor)
+{
+ Q_UNUSED(oldMajor);
+ Q_UNUSED(oldMinor);
+ Q_UNUSED(newMajor);
+ Q_UNUSED(newMinor);
+}
+
bool Database::open()
{
Q_D(Database);
@@ -357,9 +391,16 @@ bool Database::open()
}
}
+void Database::close()
+{
+ Q_D(Database);
+ d->db.close();
+}
+
QSqlQuery Database::exec(QString sql)
{
Q_D(Database);
+ qDebug() <db.exec(sql);
if(d->db.lastError().type() != QSqlError::NoError)
qWarning(d->db.lastError().text().toLatin1().data());
diff --git a/src/database.h b/src/database.h
index 91896da..18de998 100644
--- a/src/database.h
+++ b/src/database.h
@@ -45,6 +45,7 @@ public:
Database(QObject *parent = 0);
bool open();
+ void close();
QSqlQuery exec(QString sql);
@@ -65,6 +66,9 @@ public:
SqlGeneratorBase *sqlGenertor() const;
+protected:
+ virtual void databaseUpdated(int oldMajor, int oldMinor, int newMajor, int newMinor);
+
public slots:
void setDatabaseName(QString databaseName);
void setHostName(QString hostName);
diff --git a/src/database_p.h b/src/database_p.h
index 2382105..6ce02b0 100644
--- a/src/database_p.h
+++ b/src/database_p.h
@@ -27,6 +27,7 @@
#include
+QT_BEGIN_NAMESPACE
class DatabasePrivate
{
@@ -63,4 +64,6 @@ public:
TableSet *changeLogs;
};
+QT_END_NAMESPACE
+
#endif // DATABASE_P_H
diff --git a/src/defines.h b/src/defines.h
index 390e54d..d7bd16b 100644
--- a/src/defines.h
+++ b/src/defines.h
@@ -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(QT_STRINGIFY(__nut_NAME_PERFIX __nut_DB_VERSION), QT_STRINGIFY(#major "." #minor))
#define NUT_DECLARE_TABLE(type, name) \
- Q_CLASSINFO(__nut_NAME_PERFIX __nut_TABLE " " #type, #name) \
+ Q_CLASSINFO(QT_STRINGIFY(__nut_NAME_PERFIX __nut_TABLE " " #type), #name) \
Q_PROPERTY(type* name READ name) \
Q_PROPERTY(TableSet name##s READ name##s) \
type* m_##name; \
@@ -49,7 +49,7 @@ public: \
//Table
#define NUT_DECLARE_FIELD(type, name, read, write) \
Q_PROPERTY(type name READ read WRITE write) \
- Q_CLASSINFO(__nut_NAME_PERFIX #name " " __nut_FIELD, #name) \
+ Q_CLASSINFO(QT_STRINGIFY(__nut_NAME_PERFIX #name " " __nut_FIELD), #name) \
type m_##name; \
public: \
static FieldPhrase name##Field(){ \
@@ -67,7 +67,7 @@ public: \
#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) \
+ Q_CLASSINFO(QT_STRINGIFY(__nut_NAME_PERFIX #name "Id " __nut_FOREGION_KEY), #type) \
type *m_##name; \
public: \
type *read() const { return m_##name ; } \
@@ -89,14 +89,14 @@ public: \
#define NUT_INDEX(name, field, order)
-#define NUT_PRIMARY_KEY(x) Q_CLASSINFO(__nut_NAME_PERFIX #x " " __nut_PRIMARY_KEY, #x)
-#define NUT_AUTO_INCREMENT(x) Q_CLASSINFO(__nut_NAME_PERFIX #x " " __nut_AUTO_INCREMENT, #x)
+#define NUT_PRIMARY_KEY(x) Q_CLASSINFO(QT_STRINGIFY(__nut_NAME_PERFIX #x " " __nut_PRIMARY_KEY), #x)
+#define NUT_AUTO_INCREMENT(x) Q_CLASSINFO(QT_STRINGIFY(__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")
+#define NUT_UNIQUE(x) Q_CLASSINFO(QT_STRINGIFY(__nut_NAME_PERFIX #x " " __nut_UNIQUE), #x)
+#define NUT_LEN(x, n) Q_CLASSINFO(QT_STRINGIFY(__nut_NAME_PERFIX #x " " __nut_LEN), #n)
+#define NUT_DEFAULT_VALUE(x, n) Q_CLASSINFO(QT_STRINGIFY(__nut_NAME_PERFIX #x " " __nut_DEFAULT_VALUE), #n)
+#define NUT_NOT_NULL(x) Q_CLASSINFO(QT_STRINGIFY(__nut_NAME_PERFIX #x " " __nut_NOT_NULL), "1")
#ifndef NUT_NO_KEYWORDS
# define FROM(x) /*QScopedPointer*/(x->createQuery())
@@ -111,4 +111,6 @@ public: \
# define FIRST() ->first()
#endif // NUT_NO_KEYWORDS
+
+
#endif // SYNTAX_DEFINES_H
diff --git a/src/query.cpp b/src/query.cpp
index de01254..4412232 100644
--- a/src/query.cpp
+++ b/src/query.cpp
@@ -1,4 +1,4 @@
-/**************************************************************************
+/*!************************************************************************
**
** This file is part of Nut project.
** https://github.com/HamedMasafi/Nut
@@ -20,4 +20,48 @@
#include "query.h"
+QT_BEGIN_NAMESPACE
+QueryPrivate::QueryPrivate(QueryBase *parent) : q_ptr(parent),
+ joinClassName(QString::null)
+{
+
+}
+
+/*!
+ * \class Query
+ * \brief This class hold a query. A query can be used for getting database rows, editing or deleting without row fetching.
+ */
+
+/*!
+ * \brief toList
+ * \param count Total rows must be returned
+ * \return This function return class itself
+ * This function return rows
+ */
+
+/*!
+ * \brief setWhere
+ * \param where Where phrase
+ * \return This function return class itself
+ */
+
+/*!
+ * \brief orderBy
+ * \param phrase Order phrase
+ * \return This function return class itself
+ * orderBy set a new order for this query. Order can be a hrase like that:
+ * \code
+ * query->orderBy(Post::idField());
+ * \endcode
+ * If you need more than one order field seprate them by & operator, example:
+ * \code
+ * query->orderBy(Post::idField() & Post::bodyField());
+ * \endcode
+ * Order can be also DESC, for that put exclamation mark near field
+ * \code
+ * query->orderBy(!Post::idField & Post::bodyField());
+ * \endcode
+ */
+
+QT_END_NAMESPACE
diff --git a/src/query.h b/src/query.h
index 99c32d3..029f675 100644
--- a/src/query.h
+++ b/src/query.h
@@ -26,6 +26,7 @@
#include
#include
+#include "query_p.h"
#include "database.h"
#include "databasemodel.h"
#include "tablesetbase_p.h"
@@ -38,74 +39,87 @@ QT_BEGIN_NAMESPACE
template
class NUT_EXPORT Query : public QueryBase
{
- QString _tableName;
- QString _select;
-// QString _where;
- Database *_database;
- TableSetBase *_tableSet;
- QString _joinClassName;
- QList _wheres;
+ QueryPrivate *d_ptr;
+ Q_DECLARE_PRIVATE(Query)
+
public:
Query(Database *database, TableSetBase *tableSet);
-
- Query(TableSet *tset){
- _database = tset->database();
- _tableName = _database->tableName(T::staticMetaObject.className());
- }
+ ~Query();
QList toList(int count = -1);
- T *first();
- int count();
int remove();
+ T *first();
+
+ int count();
+
+ QVariant max(FieldPhrase &f);
+ QVariant min(FieldPhrase &f);
+ QVariant average(FieldPhrase &f){
+ //TODO: ...
+ return QVariant();
+ }
Query *join(const QString &tableName);
Query *setWhere(WherePhrase where);
+
+ Query *join(Table *c){
+ join(c->metaObject()->className());
+ return this;
+ }
+
// Query *setWhere(const QString &where);
Query *orderBy(QString fieldName, QString type);
-
-private:
- static QHash _compiledCommands;
- QString compileCommand(QString command);
- QString queryText();
- QHash _orders;
+ Query *orderBy(WherePhrase phrase);
};
-//template
-//inline Query createQuery(TableSet *tset)
-//{
-// return Query(tset);
-//}
-
-template
-QHash Query::_compiledCommands;
-
template
Q_OUTOFLINE_TEMPLATE Query::Query(Database *database, TableSetBase *tableSet) : QueryBase(database),
- _database(database), _tableSet(tableSet), _joinClassName(QString::null)
+ d_ptr(new QueryPrivate(this))
{
- _tableName = _database->tableName(T::staticMetaObject.className());
+ Q_D(Query);
+
+ d->database = database;
+ d->tableSet = tableSet;
+ d->tableName = d->database->tableName(T::staticMetaObject.className());
+}
+
+template
+Q_OUTOFLINE_TEMPLATE Query::~Query()
+{
+ qDebug() << "Query::~Query()";
+ Q_D(Query);
+ delete d;
}
template
Q_OUTOFLINE_TEMPLATE QList Query::toList(int count)
{
+ Q_D(Query);
QList result;
- _select = "*";
- qDebug()<exec(_database->sqlGenertor()->selectCommand(_wheres, _orders, _tableName, _joinClassName));
+ d->select = "*";
- QString pk =_database->model().model(_tableName)->primaryKey();
+// QSqlQuery q = d->database->exec(d->database->sqlGenertor()->selectCommand(d->wheres, d->orders, d->tableName, d->joinClassName));
+ QSqlQuery q = d->database->exec(d->database->sqlGenertor()->selectCommand(
+ SqlGeneratorBase::SelectALl,
+ "",
+ d->wheres,
+ d->orderPhrases,
+ d->tableName,
+ d->joinClassName));
+
+ QString pk =d->database->model().model(d->tableName)->primaryKey();
QVariant lastPkValue = QVariant();
int childTypeId = 0;
T *lastRow = 0;
TableSetBase *childTableSet;
- QStringList masterFields = _database->model().model(_tableName)->fieldsNames();
+ QStringList masterFields = d->database->model().model(d->tableName)->fieldsNames();
QStringList childFields;
- if(!_joinClassName.isNull()){
- childFields = _database->model().modelByClass(_joinClassName)->fieldsNames();
- QString joinTableName = _database->tableName(_joinClassName);
- childTypeId = _database->model().model(joinTableName)->typeId();
- }
+ if(!d->joinClassName.isNull())
+ if(d->database->model().modelByClass(d->joinClassName)){
+ childFields = d->database->model().modelByClass(d->joinClassName)->fieldsNames();
+ QString joinTableName = d->database->tableName(d->joinClassName);
+ childTypeId = d->database->model().model(joinTableName)->typeId();
+ }
while (q.next()) {
if(lastPkValue != q.value(pk)){
@@ -114,7 +128,7 @@ Q_OUTOFLINE_TEMPLATE QList Query::toList(int count)
foreach (QString field, masterFields)
t->setProperty(field.toLatin1().data(), q.value(field));
- t->setTableSet(_tableSet);
+ t->setTableSet(d->tableSet);
t->setStatus(Table::FeatchedFromDB);
t->setParent(this);
@@ -124,7 +138,7 @@ Q_OUTOFLINE_TEMPLATE QList Query::toList(int count)
if(childTypeId){
QSet tableSets = t->tableSets;
foreach (TableSetBase *ts, tableSets)
- if(ts->childClassName() == _joinClassName)
+ if(ts->childClassName() == d->joinClassName)
childTableSet = ts;
}
}
@@ -166,8 +180,33 @@ Q_OUTOFLINE_TEMPLATE T *Query::first()
template
Q_OUTOFLINE_TEMPLATE int Query::count()
{
- _select = "COUNT(*)";
- QSqlQuery q = _database->exec(queryText());
+ Q_D(Query);
+
+ d->select = "COUNT(*)";
+ QSqlQuery q = d->database->exec(d->database->sqlGenertor()->selectCommand("COUNT(*)", d->wheres, d->orders, d->tableName, d->joinClassName));
+
+ if(q.next())
+ return q.value(0).toInt();
+ return 0;
+}
+
+template
+Q_OUTOFLINE_TEMPLATE QVariant Query::max(FieldPhrase &f){
+ Q_D(Query);
+
+ QSqlQuery q = d->database->exec(d->database->sqlGenertor()->selectCommand("MAX(" + f.data()->text + ")", d->wheres, d->orders, d->tableName, d->joinClassName));
+
+ if(q.next())
+ return q.value(0).toInt();
+ return 0;
+}
+
+template
+Q_OUTOFLINE_TEMPLATE QVariant Query::min(FieldPhrase &f){
+ Q_D(Query);
+
+ QSqlQuery q = d->database->exec(d->database->sqlGenertor()->selectCommand("MIN(" + f.data()->text + ")", d->wheres, d->orders, d->tableName, d->joinClassName));
+
if(q.next())
return q.value(0).toInt();
return 0;
@@ -176,119 +215,45 @@ Q_OUTOFLINE_TEMPLATE int Query::count()
template
Q_OUTOFLINE_TEMPLATE int Query::remove()
{
- QString sql = _database->sqlGenertor()->deleteCommand(_wheres, _tableName);
-// _database->sqlGenertor()->deleteRecords(_tableName, queryText());
+ Q_D(Query);
+
+ QString sql = d->database->sqlGenertor()->deleteCommand(d->wheres, d->tableName);
+// d->_database->sqlGenertor()->deleteRecords(_tableName, queryText());
// sql = compileCommand(sql);
- QSqlQuery q = _database->exec(sql);
+ QSqlQuery q = d->database->exec(sql);
return q.numRowsAffected();
}
template
Q_OUTOFLINE_TEMPLATE Query *Query::join(const QString &tableName)
{
- _joinClassName = tableName;
+ Q_D(Query);
+ d->joinClassName = tableName;
return this;
}
template
Q_OUTOFLINE_TEMPLATE Query *Query::setWhere(WherePhrase where)
{
- _wheres.append(where);
+ Q_D(Query);
+ d->wheres.append(where);
return this;
}
-//template
-//Q_OUTOFLINE_TEMPLATE Query *Query::setWhere(const QString &where)
-//{
-// _where = where;
-// return this;
-//}
-
template
Q_OUTOFLINE_TEMPLATE Query *Query::orderBy(QString fieldName, QString type)
{
- _orders.insert(fieldName, type);
+ Q_D(Query);
+ d->orders.insert(fieldName, type);
return this;
}
template
-Q_OUTOFLINE_TEMPLATE QString Query::compileCommand(QString command)
+Q_OUTOFLINE_TEMPLATE Query *Query::orderBy(WherePhrase phrase)
{
- if(!_compiledCommands.contains(command)){
- QString q = command
- .replace("::", ".")
- .replace("()", "")
- .replace("==", "=")
- .replace("!=", "<>");
-
- QRegularExpression r("(\\w+)\\.(\\w+)");
- QRegularExpressionMatchIterator i = r.globalMatch(command);
- while (i.hasNext()) {
- QRegularExpressionMatch match = i.next();
- QString tableName = match.captured(1);
- QString fieldName = match.captured(2);
- tableName = _database->tableName(tableName);
- q = command.replace(match.captured(), tableName + "." + fieldName);
- }
- _compiledCommands.insert(command, q);
- }
-
- return _compiledCommands[command];
-}
-
-template
-Q_OUTOFLINE_TEMPLATE QString Query::queryText()
-{
- QStringList orderby;
- QString q = "";//compileCommand(_where);
- foreach (WherePhrase p, _wheres) {
- if(q != "")
- q.append(" AND ");
- q.append(p.command(_database->sqlGenertor()));
- }
-
- QString t = _tableName;
- if(!_joinClassName.isNull()){
- QString joinTableName = _database->tableName(_joinClassName);
- RelationModel *rel = _database->model().relationByTableNames(_tableName, joinTableName);
- if(rel){
- 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.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());
- _joinClassName = QString::null;
- }
- }
-
- 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(orderText);
-
- for(int i = 0; i < _database->model().count(); i++)
- command = command.replace(_database->model().at(i)->className() + "." , _database->model().at(i)->name() + ".");
-
- qDebug() << command
- << _database->sqlGenertor()->selectCommand(_wheres, _orders, _tableName, _joinClassName);
- return command;
+ Q_D(Query);
+ d->orderPhrases.append(phrase);
+ return this;
}
QT_END_NAMESPACE
diff --git a/src/query_p.h b/src/query_p.h
new file mode 100644
index 0000000..3c01804
--- /dev/null
+++ b/src/query_p.h
@@ -0,0 +1,49 @@
+/**************************************************************************
+**
+** This file is part of Nut project.
+** https://github.com/HamedMasafi/Nut
+**
+** Nut is free software: you can redistribute it and/or modify
+** it under the terms of the GNU Lesser General Public License as published by
+** the Free Software Foundation, either version 3 of the License, or
+** (at your option) any later version.
+**
+** Nut is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU Lesser General Public License for more details.
+**
+** You should have received a copy of the GNU Lesser General Public License
+** along with Nut. If not, see .
+**
+**************************************************************************/
+
+#ifndef QUERY_P_H
+#define QUERY_P_H
+
+#include "wherephrase.h"
+
+#include
+#include
+
+class Database;
+class TableSetBase;
+//template
+class QueryBase;
+class QueryPrivate{
+ QueryBase *q_ptr;
+ Q_DECLARE_PUBLIC(QueryBase)
+
+public:
+ QueryPrivate(QueryBase *parent);
+ QString tableName;
+ QString select;
+ Database *database;
+ TableSetBase *tableSet;
+ QString joinClassName;
+ QList wheres;
+ QHash orders;
+ QList orderPhrases;
+};
+
+#endif // QUERY_P_H
diff --git a/src/sqlgeneratorbase.cpp b/src/sqlgeneratorbase.cpp
index ef3ac62..e790775 100644
--- a/src/sqlgeneratorbase.cpp
+++ b/src/sqlgeneratorbase.cpp
@@ -28,6 +28,7 @@
#include "sqlgeneratorbase_p.h"
#include "table.h"
#include "tablemodel.h"
+#include "wherephrase.h"
QT_BEGIN_NAMESPACE
@@ -174,9 +175,16 @@ QString SqlGeneratorBase::insertRecord(Table *t, QString tableName)
if(f != key)
values.append("'" + t->property(f.toLatin1().data()).toString() + "'");
+ QString changedPropertiesText = "";
+ QSet props = t->changedProperties();
+ foreach (QString s, props) {
+ if(changedPropertiesText != "")
+ changedPropertiesText.append(", ");
+ changedPropertiesText.append(s);
+ }
sql = QString("INSERT INTO %1 (%2) VALUES (%3)")
.arg(tableName)
- .arg(t->changedProperties().toList().join(", "))
+ .arg(changedPropertiesText)
.arg(values.join(", "));
return sql;
@@ -208,6 +216,61 @@ QString SqlGeneratorBase::deleteRecord(Table *t, QString tableName)
.arg(t->primaryValue().toString());
}
+QString SqlGeneratorBase::agregateText(const AgregateType &t, const QString &arg) const
+{
+ switch (t) {
+ case SelectALl:
+ return "*";
+ break;
+
+ case Min:
+ return "MIN(" + arg + ")";
+ break;
+
+ case Max:
+ return "MAX(" + arg + ")";
+ break;
+
+ case Average:
+ return "AVERAGE(" + arg + ")";
+ break;
+
+ case Count:
+ return "COUNT(" + arg + ")";
+ break;
+
+ default:
+ return QString::null;
+ }
+}
+
+QString SqlGeneratorBase::fromTableText(const QString &tableName, QString &joinClassName, QString &orderBy) const
+{
+ QString tableNameText = tableName;
+ if(!joinClassName.isNull()){
+ QString joinTableName = _database->tableName(joinClassName);
+ RelationModel *rel = _database->model().relationByTableNames(tableName, joinTableName);
+ if(rel){
+ QString pk = _database->model().model(tableName)->primaryKey();
+ tableNameText = QString("%1 INNER JOIN %2 ON (%1.%3 = %2.%4)")
+ .arg(tableName)
+ .arg(joinTableName)
+ .arg(pk)
+ .arg(rel->localColumn);
+ orderBy = 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());
+ joinClassName = QString::null;
+ }
+ }
+
+ return tableNameText;
+}
+
QString SqlGeneratorBase::deleteRecords(QString tableName, QString where)
{
QString sql = "";
@@ -218,60 +281,70 @@ QString SqlGeneratorBase::deleteRecords(QString tableName, QString where)
return sql;
}
-QString SqlGeneratorBase::escapeFieldValue(QVariant &field) const
+QString SqlGeneratorBase::selectCommand(SqlGeneratorBase::AgregateType t, QString agregateArg, QList &wheres, QList &orders, QString tableName, QString joinClassName)
{
- switch (field.type()) {
- case QVariant::Int:
- case QVariant::Double:
- return field.toString();
- break;
+ QString select = agregateText(t, agregateArg);
+ QString where = createWhere(wheres);
+ QString order = "";
+ QString from = fromTableText(tableName, joinClassName, order);
- case QVariant::String:
- return "'" + field.toString() + "'";
-
- case QVariant::DateTime:
- return "'" + field.toDateTime().toString(Qt::ISODate) + "'";
-
- case QVariant::Date:
- return "'" + field.toDate().toString(Qt::ISODate) + "'";
-
- case QVariant::Time:
- return "'" + field.toTime().toString(Qt::ISODate) + "'";
-
- case QVariant::StringList:
- case QVariant::List:
- return "['" + field.toStringList().join("', '") + "']";
-
- case QVariant::Invalid:
- qFatal("Invalud field value");
- return "";
-
- default:
- return "";
+ foreach(WherePhrase p, orders){
+ if(order != "")
+ order.append(", ");
+ order.append(phraseOrder(p.data()));
}
+
+ QString sql = "SELECT " + select + " FROM " + from;
+
+ if(where != "")
+ sql.append(" WHERE " + where);
+
+ if(order != "")
+ sql.append(" ORDER BY " + order);
+
+ 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;
+}
+
+QString SqlGeneratorBase::selectCommand(QList &wheres, QHash &orders, QString tableName, QString joinClassName)
+{
+ return selectCommand("*", wheres, orders, tableName, joinClassName);
}
QString SqlGeneratorBase::createWhere(QList &wheres)
{
QString whereText = "";
- foreach (WherePhrase p, wheres) {
+// for (int i = 0; i < wheres.count(); i++) {
+// if(whereText != "")
+// whereText.append(" AND ");
+// whereText.append(phrase(wheres[i].data()));
+// }
+ foreach (WherePhrase w, wheres) {
if(whereText != "")
whereText.append(" AND ");
- whereText.append(p.command(this));
+
+ whereText.append(phrase(w.data()));
}
- if(whereText != "")
- whereText.prepend(" WHERE ");
+qDebug() << "WHWRE="<< whereText;
+// if(whereText != "")
+// whereText.prepend(" WHERE ");
return whereText;
}
-QString SqlGeneratorBase::selectCommand(QList &wheres, QHash &orders, QString tableName, QString joinClassName)
+QString SqlGeneratorBase::selectCommand(QString selectPhrase, QList &wheres, QHash &orders, QString tableName, QString joinClassName)
{
QString orderText = "";
QStringList orderby;
QString whereText = createWhere(wheres);
+ if(whereText != "")
+ whereText.prepend(" WHERE ");
+
QString tableNameText = tableName;
if(!joinClassName.isNull()){
QString joinTableName = _database->tableName(joinClassName);
@@ -302,27 +375,184 @@ QString SqlGeneratorBase::selectCommand(QList &wheres, QHashmodel().count(); i++)
command = command.replace(_database->model().at(i)->className() + "." , _database->model().at(i)->name() + ".");
+
+ qDebug() << command;
return command;
}
QString SqlGeneratorBase::deleteCommand(QList &wheres, QString tableName)
{
- QString command = "DELETE FROM "
- + tableName
- + createWhere(wheres);
+ QString command = "DELETE FROM " + tableName;
+ QString where = createWhere(wheres);
+
+ if(where != "")
+ command.append(" WHERE " + where);
for(int i = 0; i < _database->model().count(); i++)
command = command.replace(_database->model().at(i)->className() + "." , _database->model().at(i)->name() + ".");
return command;
}
+QString SqlGeneratorBase::escapeValue(const QVariant &v)const
+{
+ switch (v.type()) {
+ case QVariant::Int:
+ case QVariant::UInt:
+ case QVariant::ULongLong:
+ case QVariant::LongLong:
+ case QVariant::Double:
+ return v.toString();
+ break;
+
+ case QVariant::Char:
+ case QVariant::String:
+ return "'" + v.toString() + "'";
+
+ case QVariant::DateTime:
+ return "'" + v.toDateTime().toString() + "'";
+
+ case QVariant::Date:
+ return "'" + v.toDate().toString() + "'";
+
+ case QVariant::Time:
+ return "'" + v.toTime().toString() + "'";
+
+ case QVariant::StringList:
+ case QVariant::List:
+ return "['" + v.toStringList().join("', '") + "']";
+
+ case QVariant::Invalid:
+ qFatal("Invalud field value");
+ return "";
+ }
+ return "";
+}
+
+QString SqlGeneratorBase::phraseOrder(const PhraseData *d) const
+{
+
+ QString ret = "";
+
+ switch(d->type){
+ case PhraseData::Field:
+ if(d->operatorCond == PhraseData::Not)
+ ret = d->text + " DESC";
+ else
+ ret = d->text;
+ break;
+
+ case PhraseData::WithOther:
+ if(d->operatorCond != PhraseData::Append)
+ qFatal("Order phease can only have & operator");
+
+ ret = phraseOrder(d->left) + ", " + phraseOrder(d->right);
+ break;
+
+ case PhraseData::WithoutOperand:
+ case PhraseData::WithVariant:
+ break;
+ }
+
+ return ret;
+}
+
+QString SqlGeneratorBase::phrase(const PhraseData *d) const
+{
+ QString ret = "";
+
+ qDebug() << "type"<type;
+ switch(d->type){
+ case PhraseData::Field:
+ ret = d->text;
+ break;
+
+ case PhraseData::WithVariant:
+ ret = phrase(d->left) + " " + operatorString(d->operatorCond) + " " + escapeValue(d->operand);
+ break;
+
+ case PhraseData::WithOther:
+ ret = phrase(d->left) + " " + operatorString(d->operatorCond) + " " + phrase(d->right);
+ break;
+
+ case PhraseData::WithoutOperand:
+ ret = phrase(d->left) + " " + operatorString(d->operatorCond);
+ break;
+
+ default:
+ ret = "";
+ }
+
+ if(d->operatorCond == PhraseData::And || d->operatorCond == PhraseData::Or)
+ ret = "(" + ret + ")";
+
+ return ret;
+}
+
+QString SqlGeneratorBase::operatorString(const PhraseData::Condition &cond) const
+{
+ switch (cond){
+ 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("");
+}
+
QT_END_NAMESPACE
diff --git a/src/sqlgeneratorbase_p.h b/src/sqlgeneratorbase_p.h
index 0390dc6..06102b2 100644
--- a/src/sqlgeneratorbase_p.h
+++ b/src/sqlgeneratorbase_p.h
@@ -24,6 +24,7 @@
#include
#include
#include
+#include "wherephrase.h"
QT_BEGIN_NAMESPACE
@@ -31,8 +32,9 @@ class Table;
struct FieldModel;
class DatabaseModel;
class TableModel;
-class WherePhrase;
class Database;
+//struct PhraseData;
+//class WherePhrase;
class SqlGeneratorBase : public QObject
{
// Q_OBJECT
@@ -45,6 +47,13 @@ public:
Update,
Delete
};
+ enum AgregateType{
+ SelectALl,
+ Count,
+ Min,
+ Max,
+ Average
+ };
SqlGeneratorBase(Database *parent);
virtual ~SqlGeneratorBase();
@@ -58,23 +67,35 @@ public:
virtual QString diff(FieldModel *oldField, FieldModel *newField);
virtual QString diff(TableModel *oldTable, TableModel *newTable);
-
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 deleteRecords(QString tableName, QString where);
- virtual QString escapeFieldValue(QVariant &field) const;
+ virtual QString selectCommand(AgregateType t, QString agregateArg,
+ QList &wheres, QList &orders,
+ QString tableName, QString joinClassName);
virtual QString selectCommand(QList &wheres, QHash &orders,
QString tableName, QString joinClassName);
+ virtual QString selectCommand(QString selectPhrase,
+ QList &wheres, QHash &orders,
+ QString tableName, QString joinClassName);
virtual QString deleteCommand(QList &wheres, QString tableName);
+ virtual QString escapeValue(const QVariant &v) const;
+ virtual QString phrase(const PhraseData *d) const;
+ virtual QString operatorString(const PhraseData::Condition &cond) const;
+
private:
+ QString agregateText(const AgregateType &t, const QString &arg = QString::null) const;
+ QString fromTableText(const QString &tableName, QString &joinClassName, QString &orderBy) const;
QString createWhere(QList &wheres);
+ QString phraseOrder(const PhraseData *d) const;
};
QT_END_NAMESPACE
diff --git a/src/sqlservergenerator.cpp b/src/sqlservergenerator.cpp
index ef35b11..77bc8d1 100644
--- a/src/sqlservergenerator.cpp
+++ b/src/sqlservergenerator.cpp
@@ -102,4 +102,12 @@ QString SqlServerGenerator::diff(FieldModel *oldField, FieldModel *newField)
return sql;
}
+QString SqlServerGenerator::escapeValue(const QVariant &v) const
+{
+ if(v.type() == QVariant::String || v.type() == QVariant::Char)
+ return "N'" + v.toString() + "'";
+ else
+ return SqlGeneratorBase::escapeValue(v);
+}
+
QT_END_NAMESPACE
diff --git a/src/sqlservergenerator.h b/src/sqlservergenerator.h
index c71f21b..71a6825 100644
--- a/src/sqlservergenerator.h
+++ b/src/sqlservergenerator.h
@@ -35,6 +35,8 @@ public:
QString fieldType(FieldModel *field);
QString diff(FieldModel *oldField, FieldModel *newField);
+
+ QString escapeValue(const QVariant &v) const;
};
QT_END_NAMESPACE
diff --git a/src/tablemodel.cpp b/src/tablemodel.cpp
index de22f6e..d92093d 100644
--- a/src/tablemodel.cpp
+++ b/src/tablemodel.cpp
@@ -148,6 +148,7 @@ TableModel::TableModel(int typeId, QString tableName)
// get fields names
for(int j = 0; j < tableMetaObject->classInfoCount(); j++){
QString name = tableMetaObject->classInfo(j).name();
+ name = name.replace("\"", "");
name = name.remove(__nut_NAME_PERFIX);
@@ -181,8 +182,8 @@ TableModel::TableModel(int typeId, QString tableName)
QString name = tableMetaObject->classInfo(j).name();
QString value = tableMetaObject->classInfo(j).value();
- name = name.remove(__nut_NAME_PERFIX);
-
+ name = name.replace("\"", "").remove(__nut_NAME_PERFIX);
+ value = value.replace("\"", "");
if(name.contains(" ")){
QStringList parts = name.split(" ");
diff --git a/src/wherephrase.cpp b/src/wherephrase.cpp
index 0a442d1..ef08143 100644
--- a/src/wherephrase.cpp
+++ b/src/wherephrase.cpp
@@ -28,327 +28,249 @@ QT_BEGIN_NAMESPACE
PhraseData::PhraseData(const char *className, const char *s){
text = QString(className) + "." + s;
type = Field;
+ qDebug() << "(" << this << ")" << "Data type 0";
}
PhraseData::PhraseData(PhraseData *l, PhraseData::Condition o) : left(l){
operatorCond = o;
type = WithoutOperand;
+ 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";
}
PhraseData::PhraseData(PhraseData *l, PhraseData::Condition o, QVariant r) : left(l), operand(r){
operatorCond = o;
type = WithVariant;
+ qDebug() << "(" << this << ")" << "Data type 1";
}
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 ",";
+ qDebug() << "(" << this << ")" << "Data Deleting..." << type;
+ if(type == WithOther){
+ qDebug() << " - Other" << left << right;
+ delete left;
+ delete right;
}
-
- return QString("");
-}
-
-QString PhraseData::escapeVariant() const
-{
- switch (operand.type()) {
- case QVariant::Int:
- case QVariant::Double:
- return operand.toString();
- break;
-
- case QVariant::String:
- return "'" + operand.toString() + "'";
-
- case QVariant::DateTime:
- return "'" + operand.toDateTime().toString() + "'";
-
- case QVariant::Date:
- return "'" + operand.toDate().toString() + "'";
-
- case QVariant::Time:
- return "'" + operand.toTime().toString() + "'";
-
- case QVariant::StringList:
- case QVariant::List:
- return "['" + operand.toStringList().join("', '") + "']";
-
- case QVariant::Invalid:
- return "";
-
- default:
- return "";
+ if(type == WithVariant){
+ qDebug() << " - Variant" << left;
+ if(left)
+ delete left;
}
}
-QString PhraseData::command(SqlGeneratorBase *generator) const
+PhraseData *WherePhrase::data() const
{
- QString ret = "";
+ return _data;
+}
- switch(type){
- case Field:
- ret = text;
- break;
+WherePhrase::WherePhrase(const char *className, const char *s)
+{
+ qDebug() << "(" << this << ")" << "class ctor" << className << s;
+ _data = new PhraseData(className, s);
+}
- case WithVariant:
- ret = left->command(generator) + " " + operatorString() + " " + escapeVariant();
- break;
+WherePhrase::WherePhrase(const WherePhrase &l)
+{
+ _data = l._data;
+ // l._data = 0;
+ qDebug() << "(" << this << ")" << "Copy ctor, from" << _data << (&l);
+ _dataPointer = QSharedPointer(l._dataPointer);
+}
- case WithOther:
- ret = left->command(generator) + " " + operatorString() + " " + right->command(generator);
- break;
+WherePhrase::WherePhrase(WherePhrase *l)
+{
+ _data = l->_data;
- case WithoutOperand:
- ret = left->command(generator) + " " + operatorString();
- break;
- }
+ qDebug() << "(" << this << ")" << "From pointer" << _data;
+// _dataPointer = QSharedPointer(_data);
+ l->_data = 0;
+ l->_dataPointer.reset(0);
+}
- if(operatorCond == PhraseData::And || operatorCond == PhraseData::Or)
- ret = "(" + ret + ")";
-
- return ret;
+WherePhrase::WherePhrase(WherePhrase *l, PhraseData::Condition o)
+{
+ _data = new PhraseData(l->_data, o);
+// _dataPointer = QSharedPointer(_data);
+ l->_data = 0;
+ qDebug() << "(" << this << ")" << "From cond, " << _data << o;
+ l->_dataPointer.reset(0);
}
-WherePhrase::WherePhrase(const char *className, const char *s) : willDeleteData(false)
+WherePhrase::WherePhrase(WherePhrase *l, PhraseData::Condition o, WherePhrase *r)
{
- data = new PhraseData(className, s);
- text = QString(className) + "." + s;
+ _data = new PhraseData(l->_data, o, r->_data);
+// _dataPointer = QSharedPointer(_data);
+ l->_data = 0;
+ r->_data = 0;
+
+ qDebug() << "(" << this << ")" << "From two pointer" << _data;
+ l->_dataPointer.reset(0);
+ r->_dataPointer.reset(0);
}
-WherePhrase::WherePhrase(PhraseData *l) : willDeleteData(false)
+WherePhrase::WherePhrase(WherePhrase *l, PhraseData::Condition o, QVariant r)
{
- data = l;
-}
+ _data = new PhraseData(l->_data, o, r);
+// _dataPointer = QSharedPointer(_data);
+ l->_data = 0;
-WherePhrase::WherePhrase(PhraseData *l, PhraseData::Condition o) : willDeleteData(false)
-{
- data = new PhraseData(l, o);
-}
-
-
-WherePhrase::WherePhrase(PhraseData *l, PhraseData::Condition o, PhraseData *r) : willDeleteData(false)
-{
- data = new PhraseData(l, o, r);
-}
-
-WherePhrase::WherePhrase(PhraseData *l, PhraseData::Condition o, QVariant r) : willDeleteData(false)
-{
- data = new PhraseData(l, o, r);
+ qDebug() << "(" << this << ")" << "From variant," << _data << l << r;
+ l->_dataPointer.reset(0);
}
WherePhrase::~WherePhrase()
{
-// if(willDeleteData)
-// delete data;
+ qDebug() << "(" << this << ")" << "Dtor" << _data << _dataPointer.data();
+ // if(_data){
+ // delete _data;
+ // qDebug() << "deleted";
+ // }
}
-
-QString WherePhrase::command(SqlGeneratorBase *generator)
+WherePhrase WherePhrase::operator ==(const WherePhrase &other)
{
- willDeleteData = true;
- return data->command(generator);
+ return WherePhrase(this, PhraseData::Equal, (WherePhrase*)&other);
}
-void WherePhrase::deleteData(PhraseData *d)
+WherePhrase WherePhrase::operator !=(const WherePhrase &other)
{
- deleteData(d);
- if(d->type == PhraseData::WithOther){
- delete d->left;
- delete d->right;
- }
- if(d->type == PhraseData::WithVariant)
- delete d->left;
+ return WherePhrase(this, PhraseData::NotEqual, (WherePhrase*)&other);
}
-WherePhrase WherePhrase::operator ==(const WherePhrase &other){
- return WherePhrase(this->data, PhraseData::Equal, other.data);
+WherePhrase WherePhrase::operator <(const WherePhrase &other)
+{
+ return WherePhrase(this, PhraseData::Less, (WherePhrase*)&other);
}
-WherePhrase WherePhrase::operator !=(const WherePhrase &other){
- return WherePhrase(this->data, PhraseData::NotEqual, other.data);
+WherePhrase WherePhrase::operator >(const WherePhrase &other)
+{
+ return WherePhrase(this, PhraseData::Greater, (WherePhrase*)&other);
}
-WherePhrase WherePhrase::operator <(const WherePhrase &other){
- return WherePhrase(this->data, PhraseData::Less, other.data);
+WherePhrase WherePhrase::operator <=(const WherePhrase &other)
+{
+ return WherePhrase(this, PhraseData::LessEqual, (WherePhrase*)&other);
}
-WherePhrase WherePhrase::operator >(const WherePhrase &other){
- return WherePhrase(this->data, PhraseData::Greater, other.data);
-}
-
-WherePhrase WherePhrase::operator <=(const WherePhrase &other){
- return WherePhrase(this->data, PhraseData::LessEqual, other.data);
-}
-
-WherePhrase WherePhrase::operator >=(const WherePhrase &other){
- return WherePhrase(this->data, PhraseData::GreaterEqual, other.data);
+WherePhrase WherePhrase::operator >=(const WherePhrase &other)
+{
+ return WherePhrase(this, PhraseData::GreaterEqual, (WherePhrase*)&other);
}
WherePhrase WherePhrase::operator =(const WherePhrase &other)
{
- return WherePhrase(this->data, PhraseData::Set, other.data);
+ return WherePhrase(this, PhraseData::Set, (WherePhrase*)&other);
}
-WherePhrase WherePhrase::operator +(const WherePhrase &other){
- return WherePhrase(this->data, PhraseData::Add, other.data);
+WherePhrase WherePhrase::operator +(const WherePhrase &other)
+{
+ return WherePhrase(this, PhraseData::Add, (WherePhrase*)&other);
}
-WherePhrase WherePhrase::operator -(const WherePhrase &other){
- return WherePhrase(this->data, PhraseData::Minus, other.data);
+WherePhrase WherePhrase::operator -(const WherePhrase &other)
+{
+ return WherePhrase(this, PhraseData::Minus, (WherePhrase*)&other);
}
-WherePhrase WherePhrase::operator *(const WherePhrase &other){
- return WherePhrase(this->data, PhraseData::Multiple, other.data);
+WherePhrase WherePhrase::operator *(const WherePhrase &other)
+{
+ return WherePhrase(this, PhraseData::Multiple, (WherePhrase*)&other);
}
-WherePhrase WherePhrase::operator /(const WherePhrase &other){
- return WherePhrase(this->data, PhraseData::Divide, other.data);
+WherePhrase WherePhrase::operator /(const WherePhrase &other)
+{
+ return WherePhrase(this, PhraseData::Divide, (WherePhrase*)&other);
}
-WherePhrase WherePhrase::operator &&(const WherePhrase &other){
- return WherePhrase(this->data, PhraseData::And, other.data);
+WherePhrase WherePhrase::operator &&(const WherePhrase &other)
+{
+ return WherePhrase(this, PhraseData::And, (WherePhrase*)&other);
}
-WherePhrase WherePhrase::operator ||(const WherePhrase &other){
- return WherePhrase(this->data, PhraseData::Or, other.data);
+WherePhrase WherePhrase::operator ||(const WherePhrase &other)
+{
+ return WherePhrase(this, PhraseData::Or, (WherePhrase*)&other);
}
WherePhrase WherePhrase::operator &(const WherePhrase &other)
{
- return WherePhrase(this->data, PhraseData::Append, other.data);
+ qDebug() << "append" << this << (&other);
+ return WherePhrase(this, PhraseData::Append, (WherePhrase*)&other);
}
-WherePhrase FieldPhrase::operator !(){
- if(data->operatorCond < 20)
- data->operatorCond = (PhraseData::Condition)((data->operatorCond + 10) % 20);
+WherePhrase FieldPhrase::operator !()
+{
+ if(_data->operatorCond < 20)
+ _data->operatorCond = (PhraseData::Condition)((_data->operatorCond + 10) % 20);
else
qFatal("Operator ! can not aplied to non condition statements");
- return WherePhrase(data);
+ return this;//WherePhrase(this, PhraseData::Not);
}
-WherePhrase WherePhrase::operator ==(const QVariant &other){
- return WherePhrase(this->data, PhraseData::Equal, other);
-}
-
-WherePhrase WherePhrase::operator !=(const QVariant &other){
- return WherePhrase(this->data, PhraseData::NotEqual, other);
-}
-
-WherePhrase WherePhrase::operator <(const QVariant &other){
- return WherePhrase(this->data, PhraseData::Less, other);
-}
-
-WherePhrase WherePhrase::operator >(const QVariant &other){
- qDebug() << "var";
- return WherePhrase(this->data, PhraseData::Greater, other);
-}
-
-WherePhrase WherePhrase::operator <=(const QVariant &other){
- return WherePhrase(this->data, PhraseData::LessEqual, other);
-}
-
-WherePhrase WherePhrase::operator >=(const QVariant &other){
- return WherePhrase(this->data, PhraseData::GreaterEqual, other);
-}
-
-WherePhrase FieldPhrase::operator =(const QVariant &other)
+WherePhrase WherePhrase::operator ==(const QVariant &other)
{
- return WherePhrase(this->data, PhraseData::Set, other);
+ return WherePhrase(this, PhraseData::Equal, other);
+}
+
+WherePhrase WherePhrase::operator !=(const QVariant &other)
+{
+ return WherePhrase(this, PhraseData::NotEqual, other);
+}
+
+WherePhrase WherePhrase::operator <(const QVariant &other)
+{
+ return WherePhrase(this, PhraseData::Less, other);
+}
+
+WherePhrase WherePhrase::operator >(const QVariant &other)
+{
+ return WherePhrase(this, PhraseData::Greater, other);
+}
+
+WherePhrase WherePhrase::operator <=(const QVariant &other)
+{
+ return WherePhrase(this, PhraseData::LessEqual, other);
+}
+
+WherePhrase WherePhrase::operator >=(const QVariant &other)
+{
+ return WherePhrase(this, PhraseData::GreaterEqual, other);
}
FieldPhrase::FieldPhrase(const char *className, const char *s) : WherePhrase(className, s)
{
- data = new PhraseData(className, s);
- text = QString(className) + "." + s;
+ qDebug() << "(" << this << ")" << "FieldPhrase ctor" << className << s;
}
-WherePhrase FieldPhrase::operator &(const QVariant &other)
+WherePhrase FieldPhrase::operator =(const QVariant &other)
{
- Q_UNUSED(other);
- qFatal("The operator & can not applied for two fields");
+ return WherePhrase(this, PhraseData::Set, other);
}
WherePhrase FieldPhrase::isNull(){
- return WherePhrase(this->data, PhraseData::Null);
+ return WherePhrase(this, PhraseData::Null);
}
WherePhrase FieldPhrase::in(QVariantList list)
{
- return WherePhrase(this->data, PhraseData::In, list);
+ return WherePhrase(this, PhraseData::In, list);
}
WherePhrase FieldPhrase::in(QStringList list)
{
- return WherePhrase(this->data, PhraseData::In, list);
+ return WherePhrase(this, PhraseData::In, list);
}
WherePhrase FieldPhrase::like(QString pattern)
{
- return WherePhrase(this->data, PhraseData::Like, pattern);
+ return WherePhrase(this, PhraseData::Like, pattern);
}
QT_END_NAMESPACE
diff --git a/src/wherephrase.h b/src/wherephrase.h
index e60a4e1..d767c9f 100644
--- a/src/wherephrase.h
+++ b/src/wherephrase.h
@@ -27,21 +27,25 @@
#include
#include
#include
+#include
QT_BEGIN_NAMESPACE
class SqlGeneratorBase;
-struct PhraseData{
+class PhraseData{
+public:
enum Condition
{
- Equal = 0,
+ NotAssign = 0,
+ Equal,
Less,
LessEqual,
Null,
In,
Like,
- NotEqual = 10,
+ Not = 10,
+ NotEqual,
GreaterEqual,
Greater,
NotNull,
@@ -51,6 +55,7 @@ struct PhraseData{
And = 20,
Or,
+
Append,
Set,
@@ -81,34 +86,24 @@ struct PhraseData{
PhraseData(PhraseData *l, Condition o, QVariant r);
~PhraseData();
-
- QString operatorString() const;
- QString escapeVariant() const;
- QString command(SqlGeneratorBase *generator) const;
};
class WherePhrase{
protected:
- PhraseData *data;
- bool willDeleteData;
+ PhraseData *_data;
+ QSharedPointer _dataPointer;
public:
-
- QString text;
-
WherePhrase(const char *className, const char* s);
- WherePhrase(PhraseData *l);
- WherePhrase(PhraseData *l, PhraseData::Condition o);
- WherePhrase(PhraseData *l, PhraseData::Condition o, PhraseData *r);
- WherePhrase(PhraseData *l, PhraseData::Condition o, QVariant r);
+ WherePhrase(const WherePhrase &l);
+ WherePhrase(WherePhrase *l);
+ WherePhrase(WherePhrase *l, PhraseData::Condition o);
+ WherePhrase(WherePhrase *l, PhraseData::Condition o, WherePhrase *r);
+ WherePhrase(WherePhrase *l, PhraseData::Condition o, QVariant r);
~WherePhrase();
- QString command(SqlGeneratorBase *generator);
-
- void deleteData(PhraseData *d);
-
WherePhrase operator ==(const WherePhrase &other);
WherePhrase operator !=(const WherePhrase &other);
WherePhrase operator <(const WherePhrase &other);
@@ -137,14 +132,13 @@ public:
WherePhrase operator >=(const QVariant &other);
+ PhraseData *data() const;
};
class FieldPhrase: public WherePhrase{
public:
FieldPhrase(const char *className, const char* s);
- WherePhrase operator &(const QVariant &other);
-
WherePhrase operator =(const QVariant &other);
WherePhrase operator !();
@@ -154,6 +148,13 @@ public:
WherePhrase like(QString pattern);
};
+
+//TODO: make FieldPhrase template class
+//template
+//class FieldPhrase: public WherePhrase{
+
+//};
+
QT_END_NAMESPACE
#endif // PHRASE_H
diff --git a/test/basic/maintest.cpp b/test/basic/maintest.cpp
index 4d66ea2..281147c 100644
--- a/test/basic/maintest.cpp
+++ b/test/basic/maintest.cpp
@@ -33,6 +33,11 @@ void MainTest::initTestCase()
bool ok = db.open();
QTEST_ASSERT(ok);
+
+ FROM(db.comments())
+ DELETE();
+ FROM(db.posts())
+ DELETE();
}
void MainTest::dataScheema()
@@ -67,13 +72,36 @@ void MainTest::createPost()
qDebug() << "New post inserted with id:" << newPost->id();
}
+void MainTest::createPost2()
+{
+ Post *newPost = new Post;
+ newPost->setTitle("post title");
+ newPost->setSaveDate(QDateTime::currentDateTime());
+
+ db.posts()->append(newPost);
+ db.saveChanges();
+
+ for(int i = 0 ; i < 3; i++){
+ Comment *comment = new Comment;
+ comment->setMessage("comment #" + QString::number(i));
+ comment->setSaveDate(QDateTime::currentDateTime());
+ comment->setPostId(newPost->id());
+ db.comments()->append(comment);
+ }
+ db.saveChanges();
+
+ QTEST_ASSERT(newPost->id() != 0);
+ qDebug() << "New post2 inserted with id:" << newPost->id();
+}
+
void MainTest::selectPosts()
{
// auto q = FROM(db.posts())
// JOIN(Comment)
// WHERE(Post::idField() == postId);
auto q = db.posts()->createQuery();
- q->join("Comment");
+ q->join(Post::commentsTable());
+ q->orderBy(!Post::saveDateField() & Post::bodyField());
q->setWhere(Post::idField() == postId);
auto posts = q->toList();
@@ -91,6 +119,15 @@ void MainTest::selectPosts()
db.cleanUp();
}
+void MainTest::selectPostsWithoutTitle()
+{
+ auto q = db.posts()->createQuery();
+ q->setWhere(Post::titleField().isNull());
+ auto count = q->count();
+ qDebug() << "selectPostsWithoutTitle, count=" << count;
+ QTEST_ASSERT(count == 0);
+}
+
void MainTest::testDate()
{
QDateTime d = QDateTime::currentDateTime();
@@ -116,15 +153,22 @@ void MainTest::testDate()
void MainTest::selectWithInvalidRelation()
{
- auto q = FROM(db.posts())
- JOIN(Invalid_Class_Name)
- SELECT();
+ auto q = db.posts()->createQuery();
+ q->join("Invalid_Class_Name");
+ q->toList();
+}
+
+void MainTest::select10NewstPosts()
+{
+ auto q = db.posts()->createQuery();
+ q->orderBy(!Post::saveDateField());
+ q->toList(10);
}
void MainTest::modifyPost()
{
- auto q = FROM(db.posts())
- WHERE(Post::idField() == postId);
+ auto q = db.posts()->createQuery();
+ q->setWhere(Post::idField() == postId);
Post *post = q->first();
diff --git a/test/basic/maintest.h b/test/basic/maintest.h
index 4b69640..edcee0e 100644
--- a/test/basic/maintest.h
+++ b/test/basic/maintest.h
@@ -22,9 +22,12 @@ private slots:
void dataScheema();
void createPost();
+ void createPost2();
void selectPosts();
+ void selectPostsWithoutTitle();
void testDate();
void selectWithInvalidRelation();
+ void select10NewstPosts();
void modifyPost();
void deletePost();
};
diff --git a/test/basic/tst_basic.pro b/test/basic/tst_basic.pro
index ff00896..b072765 100644
--- a/test/basic/tst_basic.pro
+++ b/test/basic/tst_basic.pro
@@ -16,6 +16,7 @@ SOURCES += \
HEADERS += \
maintest.h \
+ ../common/consts.h \
../common/comment.h \
../common/post.h \
../common/weblogdatabase.h
diff --git a/test/benckmark/maintest.cpp b/test/benckmark/maintest.cpp
index c456dca..f8b8877 100644
--- a/test/benckmark/maintest.cpp
+++ b/test/benckmark/maintest.cpp
@@ -33,8 +33,6 @@ void MainTest::initTestCase()
bool ok = db.open();
QTEST_ASSERT(ok);
-
- QTEST_ASSERT(ok);
}
void MainTest::insert1kPost()
diff --git a/test/common/consts.h b/test/common/consts.h
index 08c7658..41c8154 100644
--- a/test/common/consts.h
+++ b/test/common/consts.h
@@ -1,11 +1,17 @@
#ifndef CONSTS_H
#define CONSTS_H
-#define DRIVER "QPSQL"
+//#define DRIVER "QPSQL"
+//#define HOST "127.0.0.1"
+//#define DATABASE "nutdb3"
+//#define USERNAME "postgres"
+//#define PASSWORD "856856"
+
+#define DRIVER "QMYSQL"
#define HOST "127.0.0.1"
-#define DATABASE "nutdb3"
-#define USERNAME "postgres"
-#define PASSWORD "856856"
+#define DATABASE "nutdb"
+#define USERNAME "root"
+#define PASSWORD "onlyonlyi"
// db.setDriver("QODBC");
// db.setHostName("127.0.0.1");