/**************************************************************************
**
** 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_H
#define QUERY_H
#include
#include
#include
#include
#include "database.h"
#include "databasemodel.h"
#include "tablesetbase_p.h"
#include "sqlgeneratorbase_p.h"
#include "querybase_p.h"
#include "wherephrase.h"
QT_BEGIN_NAMESPACE
template
class NUT_EXPORT Query : public QueryBase
{
QString _tableName;
QString _select;
// QString _where;
Database *_database;
TableSetBase *_tableSet;
QString _joinClassName;
QList _wheres;
public:
Query(Database *database, TableSetBase *tableSet);
Query(TableSet *tset){
_database = tset->database();
_tableName = _database->tableName(T::staticMetaObject.className());
}
QList toList(int count = -1);
T *first();
int count();
int remove();
Query *join(const QString &tableName);
Query *setWhere(FieldPhrase where);
// Query *setWhere(const QString &where);
Query *orderBy(QString fieldName, QString type);
private:
static QHash _compiledCommands;
QString compileCommand(QString command);
QString queryText();
QHash _orders;
};
//template
//inline Query createQuery(TableSet *tset)
//{
// return Query(tset);
//}
template
QHash Query::_compiledCommands;
template
Q_OUTOFLINE_TEMPLATE Query::Query(Database *database, TableSetBase *tableSet) : QueryBase(database),
_database(database), _tableSet(tableSet), _joinClassName(QString::null)
{
_tableName = _database->tableName(T::staticMetaObject.className());
}
template
Q_OUTOFLINE_TEMPLATE QList Query::toList(int count)
{
QList result;
_select = "*";
qDebug()<exec(queryText());
QString pk =_database->model().model(_tableName)->primaryKey();
QVariant lastPkValue = QVariant();
int childTypeId = 0;
T *lastRow = 0;
TableSetBase *childTableSet;
QStringList masterFields = _database->model().model(_tableName)->fieldsNames();
QStringList childFields;
if(!_joinClassName.isNull()){
childFields = _database->model().modelByClass(_joinClassName)->fieldsNames();
QString joinTableName = _database->tableName(_joinClassName);
childTypeId = _database->model().model(joinTableName)->typeId();
}
while (q.next()) {
if(lastPkValue != q.value(pk)){
T *t = new T();
foreach (QString field, masterFields)
t->setProperty(field.toLatin1().data(), q.value(field));
t->setTableSet(_tableSet);
t->setStatus(Table::FeatchedFromDB);
t->setParent(this);
result.append(t);
lastRow = t;
if(childTypeId){
QSet tableSets = t->tableSets;
foreach (TableSetBase *ts, tableSets)
if(ts->childClassName() == _joinClassName)
childTableSet = ts;
}
}
if(childTypeId){
const QMetaObject *childMetaObject = QMetaType::metaObjectForType(childTypeId);
Table *childTable = qobject_cast(childMetaObject->newInstance());
foreach (QString field, childFields)
childTable->setProperty(field.toLatin1().data(), q.value(field));
childTable->setParent(this);
childTable->setParentTable(lastRow);
childTable->setStatus(Table::FeatchedFromDB);
childTable->setTableSet(childTableSet);
childTableSet->add(childTable);
}
lastPkValue = q.value(pk);
if(!--count)
break;
}
deleteLater();
return result;
}
template
Q_OUTOFLINE_TEMPLATE T *Query::first()
{
QList list = toList(1);
if(list.count())
return list.first();
else
return 0;
}
template
Q_OUTOFLINE_TEMPLATE int Query::count()
{
_select = "COUNT(*)";
QSqlQuery q = _database->exec(queryText());
if(q.next())
return q.value(0).toInt();
return 0;
}
template
Q_OUTOFLINE_TEMPLATE int Query::remove()
{
QString sql = _database->sqlGenertor()->deleteRecords(_tableName, queryText());
// sql = compileCommand(sql);
QSqlQuery q = _database->exec(sql);
return q.numRowsAffected();
}
template
Q_OUTOFLINE_TEMPLATE Query *Query::join(const QString &tableName)
{
_joinClassName = tableName;
return this;
}
template
Q_OUTOFLINE_TEMPLATE Query *Query::setWhere(FieldPhrase where)
{
_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);
return this;
}
template
Q_OUTOFLINE_TEMPLATE QString Query::compileCommand(QString command)
{
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 (FieldPhrase p, _wheres) {
if(q != "")
q.append(" AND ");
q.append(p.command(_database->sqlGenertor()));
}
QString t = _tableName;
if(!_joinClassName.isNull()){
QString joinTableName = _database->tableName(_joinClassName);
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() + ".");
return command;
}
QT_END_NAMESPACE
#endif // QUERY_H