2016-05-21 16:09:03 +08:00
|
|
|
/**************************************************************************
|
|
|
|
|
**
|
|
|
|
|
** This file is part of Nut project.
|
|
|
|
|
** https://github.com/HamedMasafi/Nut
|
|
|
|
|
**
|
|
|
|
|
** Nut is free software: you can redistribute it and/or modify
|
|
|
|
|
** it under the terms of the GNU Lesser General Public License as published by
|
|
|
|
|
** the Free Software Foundation, either version 3 of the License, or
|
|
|
|
|
** (at your option) any later version.
|
|
|
|
|
**
|
|
|
|
|
** Nut is distributed in the hope that it will be useful,
|
|
|
|
|
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
** GNU Lesser General Public License for more details.
|
|
|
|
|
**
|
|
|
|
|
** You should have received a copy of the GNU Lesser General Public License
|
|
|
|
|
** along with Nut. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
**
|
|
|
|
|
**************************************************************************/
|
|
|
|
|
|
|
|
|
|
#include <QDate>
|
2018-01-10 07:05:49 +08:00
|
|
|
#include <QDebug>
|
2016-05-21 16:09:03 +08:00
|
|
|
#include <QDateTime>
|
2017-06-01 00:10:35 +08:00
|
|
|
#include <QPointF>
|
2016-05-21 16:09:03 +08:00
|
|
|
#include <QTime>
|
|
|
|
|
#include <QVariant>
|
|
|
|
|
|
2016-05-12 14:08:58 +08:00
|
|
|
#include "sqlgeneratorbase_p.h"
|
2017-10-07 18:26:05 +08:00
|
|
|
#include "../database.h"
|
|
|
|
|
#include "../table.h"
|
|
|
|
|
#include "../databasemodel.h"
|
|
|
|
|
#include "../tablemodel.h"
|
|
|
|
|
#include "../wherephrase.h"
|
2016-05-12 14:08:58 +08:00
|
|
|
|
2017-02-01 18:01:21 +08:00
|
|
|
NUT_BEGIN_NAMESPACE
|
2016-05-12 14:08:58 +08:00
|
|
|
|
2018-01-10 01:32:28 +08:00
|
|
|
/*
|
|
|
|
|
* Index:
|
|
|
|
|
* ALTER TABLE `travelLog` ADD INDEX(`driverId`);
|
|
|
|
|
*
|
|
|
|
|
* Foreign key:
|
|
|
|
|
* ALTER TABLE `travelLog`
|
|
|
|
|
* ADD CONSTRAINT `travelLog_ibfk_1`
|
|
|
|
|
* FOREIGN KEY (`driverId`)
|
|
|
|
|
* REFERENCES `account` (`id`)
|
|
|
|
|
* ON DELETE CASCADE
|
|
|
|
|
* ON UPDATE CASCADE;
|
2018-01-10 06:08:19 +08:00
|
|
|
*
|
|
|
|
|
* SELECT
|
|
|
|
|
* FROM dbo.GiftTypes
|
|
|
|
|
* INNER JOIN dbo.GiftCards ON dbo.GiftTypes.GiftTypeID = dbo.GiftCards.GiftTypeID
|
|
|
|
|
* INNER JOIN dbo.Entities ON dbo.GiftCards.GiftCardID = dbo.Entities.GiftCardID
|
2018-01-10 01:32:28 +08:00
|
|
|
*/
|
2017-08-10 23:09:41 +08:00
|
|
|
SqlGeneratorBase::SqlGeneratorBase(Database *parent)
|
|
|
|
|
: QObject((QObject *)parent)
|
2016-05-12 14:08:58 +08:00
|
|
|
{
|
2017-08-10 23:09:41 +08:00
|
|
|
if (parent)
|
2016-05-24 14:47:37 +08:00
|
|
|
_database = parent;
|
2016-05-12 14:08:58 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SqlGeneratorBase::~SqlGeneratorBase()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2016-05-21 16:09:03 +08:00
|
|
|
QString SqlGeneratorBase::masterDatabaseName(QString databaseName)
|
|
|
|
|
{
|
|
|
|
|
Q_UNUSED(databaseName);
|
|
|
|
|
return "";
|
|
|
|
|
}
|
|
|
|
|
|
2018-01-10 01:32:28 +08:00
|
|
|
QString SqlGeneratorBase::createTable(TableModel *table)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2016-05-21 16:09:03 +08:00
|
|
|
QString SqlGeneratorBase::saveRecord(Table *t, QString tableName)
|
2016-05-12 14:08:58 +08:00
|
|
|
{
|
2017-05-28 23:08:59 +08:00
|
|
|
Q_ASSERT(!tableName.isEmpty() && !tableName.isNull());
|
2017-08-10 23:09:41 +08:00
|
|
|
switch (t->status()) {
|
2016-05-12 14:08:58 +08:00
|
|
|
case Table::Added:
|
2016-05-21 16:09:03 +08:00
|
|
|
return insertRecord(t, tableName);
|
2016-05-12 14:08:58 +08:00
|
|
|
|
|
|
|
|
case Table::Deleted:
|
2016-05-21 16:09:03 +08:00
|
|
|
return deleteRecord(t, tableName);
|
2016-05-12 14:08:58 +08:00
|
|
|
|
|
|
|
|
case Table::Modified:
|
2016-05-21 16:09:03 +08:00
|
|
|
return updateRecord(t, tableName);
|
2016-05-12 14:08:58 +08:00
|
|
|
|
|
|
|
|
case Table::NewCreated:
|
|
|
|
|
case Table::FeatchedFromDB:
|
2017-08-24 23:35:23 +08:00
|
|
|
Q_UNREACHABLE();
|
2016-05-12 14:08:58 +08:00
|
|
|
}
|
2016-05-21 16:09:03 +08:00
|
|
|
|
|
|
|
|
return "";
|
2016-05-12 14:08:58 +08:00
|
|
|
}
|
|
|
|
|
|
2016-05-21 16:09:03 +08:00
|
|
|
QString SqlGeneratorBase::fieldDeclare(FieldModel *field)
|
|
|
|
|
{
|
2017-09-23 13:19:56 +08:00
|
|
|
return field->name + " " + fieldType(field) + (field->notNull ? " NOT NULL" : "");
|
2016-05-21 16:09:03 +08:00
|
|
|
}
|
|
|
|
|
|
2017-08-10 23:09:41 +08:00
|
|
|
QStringList SqlGeneratorBase::diff(DatabaseModel lastModel,
|
|
|
|
|
DatabaseModel newModel)
|
2016-05-12 14:08:58 +08:00
|
|
|
{
|
|
|
|
|
QStringList ret;
|
|
|
|
|
|
2018-01-08 17:08:10 +08:00
|
|
|
DatabaseModel unionModel = lastModel + newModel;
|
2016-05-12 14:08:58 +08:00
|
|
|
|
2018-01-08 17:08:10 +08:00
|
|
|
foreach (TableModel *table, unionModel) {
|
|
|
|
|
TableModel *oldTable = lastModel.tableByName(table->name());
|
|
|
|
|
TableModel *newTable = newModel.tableByName(table->name());
|
2017-06-01 23:38:53 +08:00
|
|
|
QString sql = diff(oldTable, newTable);
|
2018-01-08 17:08:10 +08:00
|
|
|
|
|
|
|
|
if (!sql.isEmpty())
|
|
|
|
|
ret << sql;
|
2016-05-12 14:08:58 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
2016-05-21 16:09:03 +08:00
|
|
|
QString SqlGeneratorBase::diff(FieldModel *oldField, FieldModel *newField)
|
2016-05-12 14:08:58 +08:00
|
|
|
{
|
|
|
|
|
QString sql = "";
|
2017-08-10 23:09:41 +08:00
|
|
|
if (oldField && newField)
|
|
|
|
|
if (*oldField == *newField)
|
2016-05-12 14:08:58 +08:00
|
|
|
return QString::null;
|
|
|
|
|
|
2017-08-10 23:09:41 +08:00
|
|
|
if (!newField) {
|
2016-05-12 14:08:58 +08:00
|
|
|
sql = "DROP COLUMN " + oldField->name;
|
2017-08-10 23:09:41 +08:00
|
|
|
} else {
|
|
|
|
|
if (oldField)
|
2017-06-04 16:16:06 +08:00
|
|
|
sql = "MODIFY COLUMN ";
|
2016-05-12 14:08:58 +08:00
|
|
|
else
|
|
|
|
|
sql = "ADD COLUMN ";
|
2016-05-21 16:09:03 +08:00
|
|
|
sql.append(fieldDeclare(newField));
|
2016-05-12 14:08:58 +08:00
|
|
|
}
|
|
|
|
|
return sql;
|
|
|
|
|
}
|
|
|
|
|
|
2016-05-21 16:09:03 +08:00
|
|
|
QString SqlGeneratorBase::diff(TableModel *oldTable, TableModel *newTable)
|
2016-05-12 14:08:58 +08:00
|
|
|
{
|
2017-08-10 23:09:41 +08:00
|
|
|
if (oldTable && newTable)
|
|
|
|
|
if (*oldTable == *newTable)
|
2016-05-12 14:08:58 +08:00
|
|
|
return "";
|
|
|
|
|
|
2017-08-10 23:09:41 +08:00
|
|
|
if (!newTable)
|
2016-05-12 14:08:58 +08:00
|
|
|
return "DROP TABLE " + oldTable->name();
|
|
|
|
|
|
|
|
|
|
QSet<QString> fieldNames;
|
|
|
|
|
|
2017-08-10 23:09:41 +08:00
|
|
|
if (oldTable)
|
2016-05-21 16:09:03 +08:00
|
|
|
foreach (FieldModel *f, oldTable->fields())
|
2016-05-12 14:08:58 +08:00
|
|
|
fieldNames.insert(f->name);
|
|
|
|
|
|
2016-05-21 16:09:03 +08:00
|
|
|
foreach (FieldModel *f, newTable->fields())
|
2016-05-12 14:08:58 +08:00
|
|
|
fieldNames.insert(f->name);
|
|
|
|
|
|
|
|
|
|
QStringList columnSql;
|
|
|
|
|
foreach (QString fieldName, fieldNames) {
|
2016-05-21 16:09:03 +08:00
|
|
|
FieldModel *newField = newTable->field(fieldName);
|
2017-08-10 23:09:41 +08:00
|
|
|
if (oldTable) {
|
2016-05-21 16:09:03 +08:00
|
|
|
FieldModel *oldField = oldTable->field(fieldName);
|
2016-05-12 14:08:58 +08:00
|
|
|
|
2017-08-10 23:09:41 +08:00
|
|
|
QString buffer = diff(oldField, newField);
|
|
|
|
|
if (!buffer.isNull())
|
2016-05-12 14:08:58 +08:00
|
|
|
columnSql << buffer;
|
2017-08-10 23:09:41 +08:00
|
|
|
} else {
|
2016-05-21 16:09:03 +08:00
|
|
|
columnSql << fieldDeclare(newField);
|
2016-05-12 14:08:58 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
QString sql;
|
2017-08-10 23:09:41 +08:00
|
|
|
if (oldTable) {
|
|
|
|
|
sql = QString("ALTER TABLE %1 \n%2").arg(newTable->name()).arg(
|
|
|
|
|
columnSql.join(",\n"));
|
|
|
|
|
} else {
|
|
|
|
|
if (!newTable->primaryKey().isNull())
|
2016-05-12 14:08:58 +08:00
|
|
|
columnSql << QString("CONSTRAINT pk_%1 PRIMARY KEY (%2)")
|
2017-08-10 23:09:41 +08:00
|
|
|
.arg(newTable->name())
|
|
|
|
|
.arg(newTable->primaryKey());
|
2016-05-12 14:08:58 +08:00
|
|
|
|
2017-08-10 23:09:41 +08:00
|
|
|
sql = QString("CREATE TABLE %1 \n(%2)").arg(newTable->name()).arg(
|
|
|
|
|
columnSql.join(",\n"));
|
2016-05-12 14:08:58 +08:00
|
|
|
}
|
|
|
|
|
return sql;
|
|
|
|
|
}
|
|
|
|
|
|
2018-01-10 01:32:28 +08:00
|
|
|
QString SqlGeneratorBase::join(const QStringList &list)
|
|
|
|
|
{
|
2018-01-10 06:08:19 +08:00
|
|
|
//TODO: make this ungly code better and bugless :-)
|
|
|
|
|
/*
|
|
|
|
|
* Known issues:
|
|
|
|
|
* Support onle near joins, far supports with medium table finding not support yet
|
|
|
|
|
*/
|
|
|
|
|
|
2018-01-10 01:32:28 +08:00
|
|
|
if (!list.count())
|
|
|
|
|
return "";
|
|
|
|
|
|
|
|
|
|
if (list.count() == 1)
|
|
|
|
|
return list.first();
|
|
|
|
|
|
|
|
|
|
DatabaseModel model = _database->model();
|
|
|
|
|
QStringList clone = list;
|
|
|
|
|
QString mainTable = clone.takeFirst();
|
|
|
|
|
QString ret = mainTable;
|
|
|
|
|
|
|
|
|
|
do {
|
2018-01-10 06:08:19 +08:00
|
|
|
QString table = model.tableByClassName(clone.first())->name();
|
|
|
|
|
clone.takeFirst();
|
|
|
|
|
RelationModel *rel = model.relationByTableNames(mainTable, table);
|
2018-01-10 01:32:28 +08:00
|
|
|
if (rel) {
|
2018-01-10 06:08:19 +08:00
|
|
|
//mainTable is master of table
|
|
|
|
|
ret.append(QString(" INNER JOIN %1 ON %4.%2 = %1.%3")
|
|
|
|
|
.arg(table)
|
|
|
|
|
.arg(rel->table->primaryKey())
|
|
|
|
|
.arg(rel->localColumn)
|
|
|
|
|
.arg(mainTable));
|
|
|
|
|
|
|
|
|
|
} else{
|
|
|
|
|
rel = model.relationByTableNames(table, mainTable);
|
|
|
|
|
if (rel) {
|
|
|
|
|
// table is master of mainTable
|
|
|
|
|
ret.append(QString(" INNER JOIN %1 ON %4.%2 = %1.%3")
|
|
|
|
|
.arg(table)
|
|
|
|
|
.arg(rel->localColumn)
|
|
|
|
|
.arg(rel->table->primaryKey())
|
|
|
|
|
.arg(mainTable));
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
qInfo("Relation for %s and %s not exists",
|
|
|
|
|
qPrintable(table), qPrintable(mainTable));
|
|
|
|
|
}
|
2018-01-10 01:32:28 +08:00
|
|
|
}
|
|
|
|
|
} while (clone.count());
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
2016-05-21 16:09:03 +08:00
|
|
|
QString SqlGeneratorBase::insertRecord(Table *t, QString tableName)
|
2016-05-12 14:08:58 +08:00
|
|
|
{
|
|
|
|
|
QString sql = "";
|
|
|
|
|
QString key = t->primaryKey();
|
|
|
|
|
QStringList values;
|
|
|
|
|
|
|
|
|
|
foreach (QString f, t->changedProperties())
|
2017-08-10 23:09:41 +08:00
|
|
|
if (f != key)
|
|
|
|
|
values.append("'" + t->property(f.toLatin1().data()).toString()
|
|
|
|
|
+ "'");
|
2016-05-12 14:08:58 +08:00
|
|
|
|
2016-06-05 20:22:26 +08:00
|
|
|
QString changedPropertiesText = "";
|
|
|
|
|
QSet<QString> props = t->changedProperties();
|
|
|
|
|
foreach (QString s, props) {
|
2017-08-10 23:09:41 +08:00
|
|
|
if (changedPropertiesText != "")
|
2016-06-05 20:22:26 +08:00
|
|
|
changedPropertiesText.append(", ");
|
|
|
|
|
changedPropertiesText.append(s);
|
|
|
|
|
}
|
2016-05-12 14:08:58 +08:00
|
|
|
sql = QString("INSERT INTO %1 (%2) VALUES (%3)")
|
2017-08-10 23:09:41 +08:00
|
|
|
.arg(tableName)
|
|
|
|
|
.arg(changedPropertiesText)
|
|
|
|
|
.arg(values.join(", "));
|
2016-05-12 14:08:58 +08:00
|
|
|
|
2017-09-10 22:18:20 +08:00
|
|
|
removeTableNames(sql);
|
2017-08-17 00:02:33 +08:00
|
|
|
|
2016-05-12 14:08:58 +08:00
|
|
|
return sql;
|
|
|
|
|
}
|
|
|
|
|
|
2016-05-21 16:09:03 +08:00
|
|
|
QString SqlGeneratorBase::updateRecord(Table *t, QString tableName)
|
2016-05-12 14:08:58 +08:00
|
|
|
{
|
|
|
|
|
QString sql = "";
|
|
|
|
|
QString key = t->primaryKey();
|
|
|
|
|
QStringList values;
|
|
|
|
|
|
|
|
|
|
foreach (QString f, t->changedProperties())
|
2017-08-10 23:09:41 +08:00
|
|
|
if (f != key)
|
|
|
|
|
values.append(f + "='" + t->property(f.toLatin1().data()).toString()
|
|
|
|
|
+ "'");
|
2016-05-12 14:08:58 +08:00
|
|
|
sql = QString("UPDATE %1 SET %2 WHERE %3=%4")
|
2017-08-10 23:09:41 +08:00
|
|
|
.arg(tableName)
|
|
|
|
|
.arg(values.join(", "))
|
|
|
|
|
.arg(key)
|
|
|
|
|
.arg(t->primaryValue().toString());
|
2016-05-12 14:08:58 +08:00
|
|
|
|
2017-09-10 22:18:20 +08:00
|
|
|
removeTableNames(sql);
|
2017-08-17 00:02:33 +08:00
|
|
|
|
2016-05-12 14:08:58 +08:00
|
|
|
return sql;
|
|
|
|
|
}
|
|
|
|
|
|
2016-05-21 16:09:03 +08:00
|
|
|
QString SqlGeneratorBase::deleteRecord(Table *t, QString tableName)
|
2016-05-12 14:08:58 +08:00
|
|
|
{
|
2017-08-17 00:02:33 +08:00
|
|
|
QString sql = QString("DELETE FROM %1 WHERE %2='%3'")
|
2017-08-10 23:09:41 +08:00
|
|
|
.arg(tableName)
|
|
|
|
|
.arg(t->primaryKey())
|
|
|
|
|
.arg(t->primaryValue().toString());
|
2017-08-17 00:02:33 +08:00
|
|
|
replaceTableNames(sql);
|
|
|
|
|
return sql;
|
2016-05-12 14:08:58 +08:00
|
|
|
}
|
|
|
|
|
|
2017-08-10 23:09:41 +08:00
|
|
|
QString SqlGeneratorBase::agregateText(const AgregateType &t,
|
|
|
|
|
const QString &arg) const
|
2016-06-05 20:22:26 +08:00
|
|
|
{
|
|
|
|
|
switch (t) {
|
2017-05-30 16:08:12 +08:00
|
|
|
case SelectAll:
|
2016-06-05 20:22:26 +08:00
|
|
|
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;
|
|
|
|
|
|
2017-05-30 16:08:12 +08:00
|
|
|
case SignleField:
|
|
|
|
|
return arg;
|
|
|
|
|
break;
|
|
|
|
|
|
2016-06-05 20:22:26 +08:00
|
|
|
default:
|
|
|
|
|
return QString::null;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-08-10 23:09:41 +08:00
|
|
|
QString SqlGeneratorBase::fromTableText(const QString &tableName,
|
|
|
|
|
QString &joinClassName,
|
|
|
|
|
QString &orderBy) const
|
2016-06-05 20:22:26 +08:00
|
|
|
{
|
|
|
|
|
QString tableNameText = tableName;
|
2017-08-10 23:09:41 +08:00
|
|
|
if (!joinClassName.isNull()) {
|
2016-06-05 20:22:26 +08:00
|
|
|
QString joinTableName = _database->tableName(joinClassName);
|
2017-08-10 23:09:41 +08:00
|
|
|
RelationModel *rel
|
|
|
|
|
= _database->model().relationByTableNames(tableName, joinTableName);
|
|
|
|
|
if (rel) {
|
|
|
|
|
QString pk = _database->model().tableByName(tableName)->primaryKey();
|
|
|
|
|
tableNameText = QString("%1 INNER JOIN %2 ON (%1.%3 = %2.%4)")
|
|
|
|
|
.arg(tableName)
|
|
|
|
|
.arg(joinTableName)
|
|
|
|
|
.arg(pk)
|
|
|
|
|
.arg(rel->localColumn);
|
2016-06-05 20:22:26 +08:00
|
|
|
orderBy = tableName + "." + pk;
|
2017-08-10 23:09:41 +08:00
|
|
|
} else {
|
2018-01-08 19:52:04 +08:00
|
|
|
qWarning("Relation between table %s and class %s (%s) not exists!",
|
|
|
|
|
qPrintable(tableName),
|
|
|
|
|
qPrintable(joinClassName),
|
|
|
|
|
qPrintable(joinTableName.isNull() ? "NULL" : joinTableName));
|
2016-06-05 20:22:26 +08:00
|
|
|
joinClassName = QString::null;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return tableNameText;
|
|
|
|
|
}
|
|
|
|
|
|
2016-05-21 16:09:03 +08:00
|
|
|
QString SqlGeneratorBase::deleteRecords(QString tableName, QString where)
|
2016-05-12 14:08:58 +08:00
|
|
|
{
|
|
|
|
|
QString sql = "";
|
2017-08-10 23:09:41 +08:00
|
|
|
if (where.isEmpty() || where.isNull())
|
2016-05-12 14:08:58 +08:00
|
|
|
sql = "DELETE FROM " + tableName;
|
|
|
|
|
else
|
|
|
|
|
sql = "DELETE FROM " + tableName + " WHERE " + where;
|
2017-08-09 21:19:35 +08:00
|
|
|
|
|
|
|
|
replaceTableNames(sql);
|
|
|
|
|
|
2016-05-12 14:08:58 +08:00
|
|
|
return sql;
|
|
|
|
|
}
|
|
|
|
|
|
2017-08-10 23:09:41 +08:00
|
|
|
QString SqlGeneratorBase::selectCommand(SqlGeneratorBase::AgregateType t,
|
|
|
|
|
QString agregateArg,
|
|
|
|
|
QList<WherePhrase> &wheres,
|
|
|
|
|
QList<WherePhrase> &orders,
|
|
|
|
|
QString tableName,
|
2017-08-24 23:35:23 +08:00
|
|
|
QString joinClassName, int skip, int take)
|
2016-05-21 16:09:03 +08:00
|
|
|
{
|
2017-09-10 22:18:20 +08:00
|
|
|
Q_UNUSED(take);
|
|
|
|
|
Q_UNUSED(skip);
|
|
|
|
|
|
2016-06-05 20:22:26 +08:00
|
|
|
QString select = agregateText(t, agregateArg);
|
|
|
|
|
QString where = createWhere(wheres);
|
|
|
|
|
QString order = "";
|
|
|
|
|
QString from = fromTableText(tableName, joinClassName, order);
|
|
|
|
|
|
2017-08-10 23:09:41 +08:00
|
|
|
foreach (WherePhrase p, orders) {
|
|
|
|
|
if (order != "")
|
2016-06-05 20:22:26 +08:00
|
|
|
order.append(", ");
|
|
|
|
|
order.append(phraseOrder(p.data()));
|
|
|
|
|
}
|
2016-05-21 16:09:03 +08:00
|
|
|
|
2016-06-05 20:22:26 +08:00
|
|
|
QString sql = "SELECT " + select + " FROM " + from;
|
2016-05-21 16:09:03 +08:00
|
|
|
|
2017-08-10 23:09:41 +08:00
|
|
|
if (where != "")
|
2017-05-30 16:08:12 +08:00
|
|
|
sql.append(" WHERE " + where);
|
|
|
|
|
|
2017-08-10 23:09:41 +08:00
|
|
|
if (order != "")
|
2017-05-30 16:08:12 +08:00
|
|
|
sql.append(" ORDER BY " + order);
|
|
|
|
|
|
2017-08-10 23:09:41 +08:00
|
|
|
for (int i = 0; i < _database->model().count(); i++)
|
|
|
|
|
sql = sql.replace(_database->model().at(i)->className() + ".",
|
|
|
|
|
_database->model().at(i)->name() + ".");
|
2017-05-30 16:08:12 +08:00
|
|
|
|
2017-08-09 21:19:35 +08:00
|
|
|
replaceTableNames(sql);
|
|
|
|
|
|
2017-05-30 16:08:12 +08:00
|
|
|
return sql;
|
|
|
|
|
}
|
|
|
|
|
|
2016-05-24 14:47:37 +08:00
|
|
|
QString SqlGeneratorBase::createWhere(QList<WherePhrase> &wheres)
|
|
|
|
|
{
|
|
|
|
|
QString whereText = "";
|
2017-08-10 23:09:41 +08:00
|
|
|
|
2016-06-05 20:22:26 +08:00
|
|
|
foreach (WherePhrase w, wheres) {
|
2017-08-10 23:09:41 +08:00
|
|
|
if (whereText != "")
|
2016-05-24 14:47:37 +08:00
|
|
|
whereText.append(" AND ");
|
2016-06-05 20:22:26 +08:00
|
|
|
|
|
|
|
|
whereText.append(phrase(w.data()));
|
2016-05-24 14:47:37 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return whereText;
|
|
|
|
|
}
|
|
|
|
|
|
2017-08-09 21:19:35 +08:00
|
|
|
void SqlGeneratorBase::replaceTableNames(QString &command)
|
|
|
|
|
{
|
|
|
|
|
foreach (TableModel *m, TableModel::allModels())
|
2017-09-10 22:18:20 +08:00
|
|
|
command = command.replace("[" + m->className() + "].", "`" + m->name() + "`.");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SqlGeneratorBase::removeTableNames(QString &command)
|
|
|
|
|
{
|
|
|
|
|
foreach (TableModel *m, TableModel::allModels())
|
|
|
|
|
command = command.replace("[" + m->className() + "].", "");
|
2017-08-09 21:19:35 +08:00
|
|
|
}
|
|
|
|
|
|
2017-08-10 23:09:41 +08:00
|
|
|
QString SqlGeneratorBase::deleteCommand(QList<WherePhrase> &wheres,
|
|
|
|
|
QString tableName)
|
2016-05-24 14:47:37 +08:00
|
|
|
{
|
2016-06-05 20:22:26 +08:00
|
|
|
QString command = "DELETE FROM " + tableName;
|
|
|
|
|
QString where = createWhere(wheres);
|
|
|
|
|
|
2017-08-10 23:09:41 +08:00
|
|
|
if (where != "")
|
2016-06-05 20:22:26 +08:00
|
|
|
command.append(" WHERE " + where);
|
2016-05-24 14:47:37 +08:00
|
|
|
|
2017-08-10 23:09:41 +08:00
|
|
|
for (int i = 0; i < _database->model().count(); i++)
|
|
|
|
|
command = command.replace(_database->model().at(i)->className() + ".",
|
|
|
|
|
_database->model().at(i)->name() + ".");
|
2017-08-09 21:19:35 +08:00
|
|
|
|
|
|
|
|
replaceTableNames(command);
|
|
|
|
|
|
2016-05-24 14:47:37 +08:00
|
|
|
return command;
|
|
|
|
|
}
|
|
|
|
|
|
2017-08-10 23:09:41 +08:00
|
|
|
QString SqlGeneratorBase::updateCommand(WherePhrase &phrase,
|
|
|
|
|
QList<WherePhrase> &wheres,
|
|
|
|
|
QString tableName)
|
2017-05-31 00:19:37 +08:00
|
|
|
{
|
|
|
|
|
QString p = this->phrase(phrase.data());
|
|
|
|
|
QString where = createWhere(wheres);
|
|
|
|
|
|
|
|
|
|
QString sql = "UPDATE " + tableName + " SET " + p;
|
|
|
|
|
|
2017-08-10 23:09:41 +08:00
|
|
|
if (where != "")
|
2017-05-31 00:19:37 +08:00
|
|
|
sql.append(" WHERE " + where);
|
|
|
|
|
|
2017-08-10 23:09:41 +08:00
|
|
|
for (int i = 0; i < _database->model().count(); i++)
|
|
|
|
|
sql = sql.replace(_database->model().at(i)->className() + ".",
|
|
|
|
|
_database->model().at(i)->name() + ".");
|
|
|
|
|
|
2017-09-10 22:18:20 +08:00
|
|
|
removeTableNames(sql);
|
2017-05-31 00:19:37 +08:00
|
|
|
|
|
|
|
|
return sql;
|
|
|
|
|
}
|
|
|
|
|
|
2017-09-10 22:18:20 +08:00
|
|
|
QString SqlGeneratorBase::joinTables(QStringList tables)
|
|
|
|
|
{
|
|
|
|
|
Q_UNUSED(tables);
|
|
|
|
|
//TODO: implement me
|
|
|
|
|
// _database->model().relationByClassNames()
|
|
|
|
|
return "";
|
|
|
|
|
}
|
|
|
|
|
|
2017-08-10 23:09:41 +08:00
|
|
|
QString SqlGeneratorBase::escapeValue(const QVariant &v) const
|
2016-06-05 20:22:26 +08:00
|
|
|
{
|
|
|
|
|
switch (v.type()) {
|
2017-02-01 18:01:21 +08:00
|
|
|
case QVariant::Bool:
|
|
|
|
|
return v.toBool() ? "1" : "0";
|
|
|
|
|
break;
|
|
|
|
|
|
2016-06-05 20:22:26 +08:00
|
|
|
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:
|
2017-06-01 00:10:35 +08:00
|
|
|
return "('" + v.toStringList().join("', '") + "')";
|
|
|
|
|
|
|
|
|
|
case QVariant::Point: {
|
|
|
|
|
QPoint pt = v.toPoint();
|
|
|
|
|
return QString("POINT(%1 %2)").arg(pt.x()).arg(pt.y());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case QVariant::PointF: {
|
|
|
|
|
QPointF pt = v.toPointF();
|
|
|
|
|
return QString("POINT(%1 %2)").arg(pt.x()).arg(pt.y());
|
|
|
|
|
}
|
2016-06-05 20:22:26 +08:00
|
|
|
|
|
|
|
|
case QVariant::Invalid:
|
|
|
|
|
qFatal("Invalud field value");
|
|
|
|
|
return "<FAIL>";
|
2017-09-10 22:18:20 +08:00
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
return "";
|
2016-06-05 20:22:26 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-08-10 23:09:41 +08:00
|
|
|
QVariant SqlGeneratorBase::readValue(const QVariant::Type &type,
|
|
|
|
|
const QVariant &dbValue)
|
2017-06-12 00:50:43 +08:00
|
|
|
{
|
2017-09-10 22:18:20 +08:00
|
|
|
Q_UNUSED(type);
|
2017-06-12 00:50:43 +08:00
|
|
|
return dbValue;
|
|
|
|
|
}
|
|
|
|
|
|
2016-06-05 20:22:26 +08:00
|
|
|
QString SqlGeneratorBase::phraseOrder(const PhraseData *d) const
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
QString ret = "";
|
|
|
|
|
|
2017-08-10 23:09:41 +08:00
|
|
|
switch (d->type) {
|
2016-06-05 20:22:26 +08:00
|
|
|
case PhraseData::Field:
|
2017-08-10 23:09:41 +08:00
|
|
|
if (d->operatorCond == PhraseData::Not)
|
2016-06-05 20:22:26 +08:00
|
|
|
ret = d->text + " DESC";
|
|
|
|
|
else
|
|
|
|
|
ret = d->text;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case PhraseData::WithOther:
|
2017-08-10 23:09:41 +08:00
|
|
|
if (d->operatorCond != PhraseData::Append)
|
2016-06-05 20:22:26 +08:00
|
|
|
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 = "";
|
|
|
|
|
|
2017-08-10 23:09:41 +08:00
|
|
|
switch (d->type) {
|
2016-06-05 20:22:26 +08:00
|
|
|
case PhraseData::Field:
|
|
|
|
|
ret = d->text;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case PhraseData::WithVariant:
|
2017-08-10 23:09:41 +08:00
|
|
|
ret = phrase(d->left) + " " + operatorString(d->operatorCond) + " "
|
|
|
|
|
+ escapeValue(d->operand);
|
2016-06-05 20:22:26 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case PhraseData::WithOther:
|
2017-08-10 23:09:41 +08:00
|
|
|
ret = phrase(d->left) + " " + operatorString(d->operatorCond) + " "
|
|
|
|
|
+ phrase(d->right);
|
2016-06-05 20:22:26 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case PhraseData::WithoutOperand:
|
|
|
|
|
ret = phrase(d->left) + " " + operatorString(d->operatorCond);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
ret = "<FAIL>";
|
|
|
|
|
}
|
|
|
|
|
|
2017-08-10 23:09:41 +08:00
|
|
|
if (d->operatorCond == PhraseData::And || d->operatorCond == PhraseData::Or)
|
2016-06-05 20:22:26 +08:00
|
|
|
ret = "(" + ret + ")";
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
2017-05-31 02:32:12 +08:00
|
|
|
QString SqlGeneratorBase::phraseUpdate(const PhraseData *d) const
|
|
|
|
|
{
|
|
|
|
|
QString ret = "";
|
|
|
|
|
|
2017-08-10 23:09:41 +08:00
|
|
|
if (d->operatorCond != PhraseData::And
|
|
|
|
|
&& d->operatorCond != PhraseData::Equal)
|
2017-05-31 02:32:12 +08:00
|
|
|
qFatal("Update command does not accept any phrase else &, =");
|
|
|
|
|
|
2017-08-10 23:09:41 +08:00
|
|
|
switch (d->type) {
|
2017-05-31 02:32:12 +08:00
|
|
|
case PhraseData::Field:
|
|
|
|
|
ret = d->text;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case PhraseData::WithVariant:
|
2017-08-10 23:09:41 +08:00
|
|
|
ret = phrase(d->left) + " " + operatorString(d->operatorCond) + " "
|
|
|
|
|
+ escapeValue(d->operand);
|
2017-05-31 02:32:12 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case PhraseData::WithOther:
|
2017-08-10 23:09:41 +08:00
|
|
|
ret = phrase(d->left) + " " + operatorString(d->operatorCond) + " "
|
|
|
|
|
+ phrase(d->right);
|
2017-05-31 02:32:12 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case PhraseData::WithoutOperand:
|
|
|
|
|
ret = phrase(d->left) + " " + operatorString(d->operatorCond);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
ret = "<FAIL>";
|
|
|
|
|
}
|
|
|
|
|
|
2017-08-10 23:09:41 +08:00
|
|
|
if (d->operatorCond == PhraseData::And || d->operatorCond == PhraseData::Or)
|
2017-05-31 02:32:12 +08:00
|
|
|
ret = "(" + ret + ")";
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
2017-08-10 23:09:41 +08:00
|
|
|
QString
|
|
|
|
|
SqlGeneratorBase::operatorString(const PhraseData::Condition &cond) const
|
2016-06-05 20:22:26 +08:00
|
|
|
{
|
2017-08-10 23:09:41 +08:00
|
|
|
switch (cond) {
|
2016-06-05 20:22:26 +08:00
|
|
|
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 ",";
|
|
|
|
|
|
2017-09-10 22:18:20 +08:00
|
|
|
default:
|
|
|
|
|
return QString("<FAIL>");
|
|
|
|
|
}
|
2016-06-05 20:22:26 +08:00
|
|
|
}
|
|
|
|
|
|
2017-02-01 18:01:21 +08:00
|
|
|
NUT_END_NAMESPACE
|