order phrase completed
This commit is contained in:
parent
e7653ddae1
commit
0a971815c4
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE QDOCINDEX>
|
||||
<INDEX url="" title="Advanced, Powerful and easy to use ORM for Qt5" version="0.1" project="Nut">
|
||||
<namespace threadsafety="unspecified" name="" status="active" access="public" module="nut"/>
|
||||
</INDEX>
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<QtHelpProject version="1.0">
|
||||
<namespace></namespace>
|
||||
<virtualFolder></virtualFolder>
|
||||
<filterSection>
|
||||
<toc>
|
||||
<section ref="index.html" title="">
|
||||
<section ref="" title=""/>
|
||||
</section>
|
||||
</toc>
|
||||
<keywords/>
|
||||
<files/>
|
||||
</filterSection>
|
||||
</QtHelpProject>
|
||||
|
|
@ -0,0 +1 @@
|
|||
da39a3ee5e6b4b0d3255bfef95601890afd80709
|
||||
Binary file not shown.
3
nut.pri
3
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 \
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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() <<sql;
|
||||
QSqlQuery q = d->db.exec(sql);
|
||||
if(d->db.lastError().type() != QSqlError::NoError)
|
||||
qWarning(d->db.lastError().text().toLatin1().data());
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
|
||||
#include <QDebug>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class DatabasePrivate
|
||||
{
|
||||
|
|
@ -63,4 +64,6 @@ public:
|
|||
TableSet<ChangeLogTable> *changeLogs;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // DATABASE_P_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<type> 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<QueryBase*>*/(x->createQuery())
|
||||
|
|
@ -111,4 +111,6 @@ public: \
|
|||
# define FIRST() ->first()
|
||||
#endif // NUT_NO_KEYWORDS
|
||||
|
||||
|
||||
|
||||
#endif // SYNTAX_DEFINES_H
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
231
src/query.h
231
src/query.h
|
|
@ -26,6 +26,7 @@
|
|||
#include <QtCore/QScopedPointer>
|
||||
#include <QtCore/QRegularExpression>
|
||||
|
||||
#include "query_p.h"
|
||||
#include "database.h"
|
||||
#include "databasemodel.h"
|
||||
#include "tablesetbase_p.h"
|
||||
|
|
@ -38,73 +39,86 @@ QT_BEGIN_NAMESPACE
|
|||
template<class T>
|
||||
class NUT_EXPORT Query : public QueryBase
|
||||
{
|
||||
QString _tableName;
|
||||
QString _select;
|
||||
// QString _where;
|
||||
Database *_database;
|
||||
TableSetBase *_tableSet;
|
||||
QString _joinClassName;
|
||||
QList<WherePhrase> _wheres;
|
||||
QueryPrivate *d_ptr;
|
||||
Q_DECLARE_PRIVATE(Query)
|
||||
|
||||
public:
|
||||
Query(Database *database, TableSetBase *tableSet);
|
||||
|
||||
Query(TableSet<T> *tset){
|
||||
_database = tset->database();
|
||||
_tableName = _database->tableName(T::staticMetaObject.className());
|
||||
}
|
||||
~Query();
|
||||
|
||||
QList<T *> 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<T> *join(const QString &tableName);
|
||||
Query<T> *setWhere(WherePhrase where);
|
||||
|
||||
Query<T> *join(Table *c){
|
||||
join(c->metaObject()->className());
|
||||
return this;
|
||||
}
|
||||
|
||||
// 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;
|
||||
Query<T> *orderBy(WherePhrase phrase);
|
||||
};
|
||||
|
||||
//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)
|
||||
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<class T>
|
||||
Q_OUTOFLINE_TEMPLATE Query<T>::~Query()
|
||||
{
|
||||
qDebug() << "Query::~Query()";
|
||||
Q_D(Query);
|
||||
delete d;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
Q_OUTOFLINE_TEMPLATE QList<T *> Query<T>::toList(int count)
|
||||
{
|
||||
Q_D(Query);
|
||||
QList<T*> result;
|
||||
_select = "*";
|
||||
qDebug()<<queryText();
|
||||
QSqlQuery q = _database->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()) {
|
||||
|
|
@ -114,7 +128,7 @@ Q_OUTOFLINE_TEMPLATE QList<T *> Query<T>::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<T *> Query<T>::toList(int count)
|
|||
if(childTypeId){
|
||||
QSet<TableSetBase*> 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<T>::first()
|
|||
template<class T>
|
||||
Q_OUTOFLINE_TEMPLATE int Query<T>::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<class T>
|
||||
Q_OUTOFLINE_TEMPLATE QVariant Query<T>::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<class T>
|
||||
Q_OUTOFLINE_TEMPLATE QVariant Query<T>::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<T>::count()
|
|||
template<class T>
|
||||
Q_OUTOFLINE_TEMPLATE int Query<T>::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<class T>
|
||||
Q_OUTOFLINE_TEMPLATE Query<T> *Query<T>::join(const QString &tableName)
|
||||
{
|
||||
_joinClassName = tableName;
|
||||
Q_D(Query);
|
||||
d->joinClassName = tableName;
|
||||
return this;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
Q_OUTOFLINE_TEMPLATE Query<T> *Query<T>::setWhere(WherePhrase where)
|
||||
{
|
||||
_wheres.append(where);
|
||||
Q_D(Query);
|
||||
d->wheres.append(where);
|
||||
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);
|
||||
Q_D(Query);
|
||||
d->orders.insert(fieldName, type);
|
||||
return this;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
Q_OUTOFLINE_TEMPLATE QString Query<T>::compileCommand(QString command)
|
||||
Q_OUTOFLINE_TEMPLATE Query<T> *Query<T>::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<class T>
|
||||
Q_OUTOFLINE_TEMPLATE QString Query<T>::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
|
||||
|
|
|
|||
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef QUERY_P_H
|
||||
#define QUERY_P_H
|
||||
|
||||
#include "wherephrase.h"
|
||||
|
||||
#include <QList>
|
||||
#include <QString>
|
||||
|
||||
class Database;
|
||||
class TableSetBase;
|
||||
//template<class T>
|
||||
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<WherePhrase> wheres;
|
||||
QHash<QString, QString> orders;
|
||||
QList<WherePhrase> orderPhrases;
|
||||
};
|
||||
|
||||
#endif // QUERY_P_H
|
||||
|
|
@ -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<QString> 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<WherePhrase> &wheres, QList<WherePhrase> &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 "<Invalid>";
|
||||
|
||||
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<WherePhrase> &wheres, QHash<QString, QString> &orders, QString tableName, QString joinClassName)
|
||||
{
|
||||
return selectCommand("*", wheres, orders, tableName, joinClassName);
|
||||
}
|
||||
|
||||
QString SqlGeneratorBase::createWhere(QList<WherePhrase> &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<WherePhrase> &wheres, QHash<QString, QString> &orders, QString tableName, QString joinClassName)
|
||||
QString SqlGeneratorBase::selectCommand(QString selectPhrase, QList<WherePhrase> &wheres, QHash<QString, QString> &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<WherePhrase> &wheres, QHash<QStrin
|
|||
if(orderby.count())
|
||||
orderText = " ORDER BY " + orderby.join(", ");
|
||||
|
||||
QString command = "SELECT * FROM "
|
||||
QString command = "SELECT "
|
||||
+selectPhrase
|
||||
+ " FROM "
|
||||
+ tableNameText
|
||||
+ whereText
|
||||
+ 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;
|
||||
return command;
|
||||
|
||||
}
|
||||
|
||||
QString SqlGeneratorBase::deleteCommand(QList<WherePhrase> &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 "<FAIL>";
|
||||
}
|
||||
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"<<d->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 = "<FAIL>";
|
||||
}
|
||||
|
||||
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("<FAIL>");
|
||||
}
|
||||
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
#include <QtCore/qglobal.h>
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QStringList>
|
||||
#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<WherePhrase> &wheres, QList<WherePhrase> &orders,
|
||||
QString tableName, QString joinClassName);
|
||||
|
||||
virtual QString selectCommand(QList<WherePhrase> &wheres, QHash<QString, QString> &orders,
|
||||
QString tableName, QString joinClassName);
|
||||
virtual QString selectCommand(QString selectPhrase,
|
||||
QList<WherePhrase> &wheres, QHash<QString, QString> &orders,
|
||||
QString tableName, QString joinClassName);
|
||||
|
||||
virtual QString deleteCommand(QList<WherePhrase> &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<WherePhrase> &wheres);
|
||||
QString phraseOrder(const PhraseData *d) const;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -35,6 +35,8 @@ public:
|
|||
|
||||
QString fieldType(FieldModel *field);
|
||||
QString diff(FieldModel *oldField, FieldModel *newField);
|
||||
|
||||
QString escapeValue(const QVariant &v) const;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -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(" ");
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
qDebug() << "(" << this << ")" << "Data Deleting..." << type;
|
||||
if(type == WithOther){
|
||||
qDebug() << " - Other" << left << right;
|
||||
delete left;
|
||||
delete right;
|
||||
}
|
||||
if(type == WithVariant){
|
||||
qDebug() << " - Variant" << left;
|
||||
if(left)
|
||||
delete left;
|
||||
}
|
||||
}
|
||||
|
||||
QString PhraseData::operatorString() const
|
||||
PhraseData *WherePhrase::data() 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 _data;
|
||||
}
|
||||
|
||||
return QString("<FAIL>");
|
||||
}
|
||||
|
||||
QString PhraseData::escapeVariant() const
|
||||
WherePhrase::WherePhrase(const char *className, const char *s)
|
||||
{
|
||||
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 "";
|
||||
}
|
||||
qDebug() << "(" << this << ")" << "class ctor" << className << s;
|
||||
_data = new PhraseData(className, s);
|
||||
}
|
||||
|
||||
QString PhraseData::command(SqlGeneratorBase *generator) const
|
||||
WherePhrase::WherePhrase(const WherePhrase &l)
|
||||
{
|
||||
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;
|
||||
_data = l._data;
|
||||
// l._data = 0;
|
||||
qDebug() << "(" << this << ")" << "Copy ctor, from" << _data << (&l);
|
||||
_dataPointer = QSharedPointer<PhraseData>(l._dataPointer);
|
||||
}
|
||||
|
||||
if(operatorCond == PhraseData::And || operatorCond == PhraseData::Or)
|
||||
ret = "(" + ret + ")";
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
WherePhrase::WherePhrase(const char *className, const char *s) : willDeleteData(false)
|
||||
WherePhrase::WherePhrase(WherePhrase *l)
|
||||
{
|
||||
data = new PhraseData(className, s);
|
||||
text = QString(className) + "." + s;
|
||||
_data = l->_data;
|
||||
|
||||
qDebug() << "(" << this << ")" << "From pointer" << _data;
|
||||
// _dataPointer = QSharedPointer<PhraseData>(_data);
|
||||
l->_data = 0;
|
||||
l->_dataPointer.reset(0);
|
||||
}
|
||||
|
||||
WherePhrase::WherePhrase(PhraseData *l) : willDeleteData(false)
|
||||
WherePhrase::WherePhrase(WherePhrase *l, PhraseData::Condition o)
|
||||
{
|
||||
data = l;
|
||||
}
|
||||
|
||||
WherePhrase::WherePhrase(PhraseData *l, PhraseData::Condition o) : willDeleteData(false)
|
||||
{
|
||||
data = new PhraseData(l, o);
|
||||
_data = new PhraseData(l->_data, o);
|
||||
// _dataPointer = QSharedPointer<PhraseData>(_data);
|
||||
l->_data = 0;
|
||||
qDebug() << "(" << this << ")" << "From cond, " << _data << o;
|
||||
l->_dataPointer.reset(0);
|
||||
}
|
||||
|
||||
|
||||
WherePhrase::WherePhrase(PhraseData *l, PhraseData::Condition o, PhraseData *r) : willDeleteData(false)
|
||||
WherePhrase::WherePhrase(WherePhrase *l, PhraseData::Condition o, WherePhrase *r)
|
||||
{
|
||||
data = new PhraseData(l, o, r);
|
||||
_data = new PhraseData(l->_data, o, r->_data);
|
||||
// _dataPointer = QSharedPointer<PhraseData>(_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, PhraseData::Condition o, QVariant r) : willDeleteData(false)
|
||||
WherePhrase::WherePhrase(WherePhrase *l, PhraseData::Condition o, QVariant r)
|
||||
{
|
||||
data = new PhraseData(l, o, r);
|
||||
_data = new PhraseData(l->_data, o, r);
|
||||
// _dataPointer = QSharedPointer<PhraseData>(_data);
|
||||
l->_data = 0;
|
||||
|
||||
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
|
||||
|
|
|
|||
|
|
@ -27,21 +27,25 @@
|
|||
#include <QDate>
|
||||
#include <QDateTime>
|
||||
#include <QTime>
|
||||
#include <QSharedPointer>
|
||||
|
||||
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<PhraseData> _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 <typename T>
|
||||
//class FieldPhrase: public WherePhrase{
|
||||
|
||||
//};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // PHRASE_H
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
};
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ SOURCES += \
|
|||
|
||||
HEADERS += \
|
||||
maintest.h \
|
||||
../common/consts.h \
|
||||
../common/comment.h \
|
||||
../common/post.h \
|
||||
../common/weblogdatabase.h
|
||||
|
|
|
|||
|
|
@ -33,8 +33,6 @@ void MainTest::initTestCase()
|
|||
bool ok = db.open();
|
||||
|
||||
QTEST_ASSERT(ok);
|
||||
|
||||
QTEST_ASSERT(ok);
|
||||
}
|
||||
|
||||
void MainTest::insert1kPost()
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
Loading…
Reference in New Issue