Nut/src/nut/generators/abstractsqlgenerator.cpp

1173 lines
37 KiB
C++
Raw Normal View History

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/>.
**
**************************************************************************/
2020-07-29 22:11:19 +08:00
#include <QtCore/QDateTime>
#include <QtCore/QPointF>
#include <QtCore/QTime>
#include <QtCore/QUuid>
#include <QtCore/QVariant>
#include <QtCore/QDebug>
2016-05-21 16:09:03 +08:00
2020-08-06 23:19:27 +08:00
#include "abstractsqlgenerator.h"
#include "database.h"
#include "table.h"
#include "databasemodel.h"
#include "tablemodel.h"
2019-02-10 17:35:35 +08:00
#include "sqlserializer.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;
*
* 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
*/
2020-08-06 23:19:27 +08:00
bool AbstractSqlGenerator::isNumeric(const QMetaType::Type &type)
2019-02-28 17:28:49 +08:00
{
return type == QMetaType::SChar
|| type == QMetaType::Char
|| type == QMetaType::UChar
|| type == QMetaType::Short
|| type == QMetaType::UShort
|| type == QMetaType::Int
|| type == QMetaType::UInt
|| type == QMetaType::Long
|| type == QMetaType::ULong
|| type == QMetaType::LongLong
|| type == QMetaType::ULongLong;
}
2020-08-06 23:19:27 +08:00
AbstractSqlGenerator::AbstractSqlGenerator(Database *parent)
2019-01-09 23:49:50 +08:00
: 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;
2019-02-08 16:39:24 +08:00
2019-02-10 17:35:35 +08:00
_serializer = new SqlSerializer;
2016-05-12 14:08:58 +08:00
}
2020-08-06 23:19:27 +08:00
QString AbstractSqlGenerator::masterDatabaseName(QString databaseName)
2016-05-21 16:09:03 +08:00
{
Q_UNUSED(databaseName)
return QString();
2016-05-21 16:09:03 +08:00
}
2020-08-06 23:19:27 +08:00
QString AbstractSqlGenerator::createTable(TableModel *table)
2018-01-10 01:32:28 +08:00
{
2018-02-24 23:43:15 +08:00
Q_UNUSED(table)
return QString();
2018-01-10 01:32:28 +08:00
}
2020-08-06 23:19:27 +08:00
QString AbstractSqlGenerator::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::FetchedFromDB:
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 QString();
2016-05-12 14:08:58 +08:00
}
2020-08-06 23:19:27 +08:00
QString AbstractSqlGenerator::recordsPhrase(TableModel *table)
2018-01-12 00:14:29 +08:00
{
if (!table)
return QString();
2018-01-12 00:14:29 +08:00
QString ret = QString();
2021-03-14 16:42:04 +08:00
Q_FOREACH (FieldModel *f, table->fields()) {
2018-01-12 00:14:29 +08:00
if (!ret.isEmpty())
2020-07-29 17:42:27 +08:00
ret.append(QLatin1String(", "));
2020-07-30 21:11:45 +08:00
ret.append(QStringLiteral("%1.%2 AS \"%1.%2\"").arg(table->name(), f->name));
2018-01-12 00:14:29 +08:00
}
return ret;
}
2020-08-06 23:19:27 +08:00
QString AbstractSqlGenerator::insertBulk(const QString &tableName, const PhraseList &ph, const QList<QVariantList> &vars)
2019-03-08 00:48:48 +08:00
{
QString sql;
2021-03-14 16:42:04 +08:00
Q_FOREACH (QVariantList list, vars) {
2019-03-08 00:48:48 +08:00
QStringList values;
2021-03-14 16:42:04 +08:00
Q_FOREACH (QVariant v, list)
2019-03-08 00:48:48 +08:00
values.append(escapeValue(v));
if (!sql.isEmpty())
2020-07-29 17:42:27 +08:00
sql.append(QLatin1String(", "));
sql.append(QLatin1String("(") + values.join(QLatin1String(", ")) + QLatin1String(")"));
2019-03-08 00:48:48 +08:00
}
2020-07-30 21:11:45 +08:00
sql = QStringLiteral("INSERT INTO %1 (%2) VALUES %3")
2020-07-29 17:42:27 +08:00
.arg(tableName, createFieldPhrase(ph), sql);
2019-03-08 00:48:48 +08:00
removeTableNames(sql);
return sql;
}
2020-08-06 23:19:27 +08:00
QString AbstractSqlGenerator::fieldDeclare(FieldModel *field)
2016-05-21 16:09:03 +08:00
{
2019-02-07 23:52:57 +08:00
QString type = fieldType(field);
if (type.isEmpty())
return type;
2020-07-29 17:42:27 +08:00
QString ret = field->name + QStringLiteral(" ") + type;
if (field->notNull)
ret.append(QStringLiteral(" NOT NULL"));
if (field->isUnique)
ret.append(QStringLiteral(" UNIQUE"));
return ret;
2016-05-21 16:09:03 +08:00
}
2020-08-06 23:19:27 +08:00
QStringList AbstractSqlGenerator::constraints(TableModel *table)
{
Q_UNUSED(table)
return QStringList();
}
2020-08-06 23:19:27 +08:00
QString AbstractSqlGenerator::relationDeclare(const RelationModel *relation)
2018-02-24 23:43:15 +08:00
{
2020-07-30 21:11:45 +08:00
return QStringLiteral("FOREIGN KEY (FK_%1) REFERENCES %2(%1)")
2019-02-10 22:11:22 +08:00
.arg(relation->localColumn, relation->slaveTable->name());
2018-02-24 23:43:15 +08:00
}
2020-08-06 23:19:27 +08:00
QStringList AbstractSqlGenerator::diff(const DatabaseModel &lastModel,
2019-02-10 22:11:22 +08:00
const DatabaseModel &newModel)
2016-05-12 14:08:58 +08:00
{
QStringList ret;
2019-02-25 22:55:16 +08:00
DatabaseModel unionModel = lastModel | newModel;
DatabaseModel::iterator i;
2016-05-12 14:08:58 +08:00
2019-02-25 22:55:16 +08:00
for (i = unionModel.begin(); i != unionModel.end(); ++i) {
TableModel *oldTable = lastModel.tableByName((*i)->name());
TableModel *newTable = newModel.tableByName((*i)->name());
2019-02-16 21:36:38 +08:00
QStringList sql = diff(oldTable, newTable);
2018-01-08 17:08:10 +08:00
if (!sql.isEmpty())
ret << sql;
2019-02-25 22:55:16 +08:00
2018-02-24 23:43:15 +08:00
// QString sqlRel = diffRelation(oldTable, newTable);
// if (!sqlRel.isEmpty())
// ret << sqlRel;
2016-05-12 14:08:58 +08:00
}
return ret;
}
2020-08-06 23:19:27 +08:00
QString AbstractSqlGenerator::diff(FieldModel *oldField, FieldModel *newField)
2016-05-12 14:08:58 +08:00
{
QString sql = QString();
2017-08-10 23:09:41 +08:00
if (oldField && newField)
if (*oldField == *newField)
2019-02-16 21:36:38 +08:00
return sql;
2016-05-12 14:08:58 +08:00
2017-08-10 23:09:41 +08:00
if (!newField) {
2020-07-29 22:11:19 +08:00
sql = QStringLiteral("DROP COLUMN ") + oldField->name;
2017-08-10 23:09:41 +08:00
} else {
if (oldField)
2020-07-29 22:11:19 +08:00
sql = QStringLiteral("MODIFY COLUMN ");
2016-05-12 14:08:58 +08:00
else
2020-07-29 22:11:19 +08:00
sql = QStringLiteral("ADD COLUMN ");
2016-05-21 16:09:03 +08:00
sql.append(fieldDeclare(newField));
2016-05-12 14:08:58 +08:00
}
return sql;
}
2020-08-06 23:19:27 +08:00
QStringList AbstractSqlGenerator::diff(TableModel *oldTable, TableModel *newTable)
2016-05-12 14:08:58 +08:00
{
if (!newTable && !oldTable)
return QStringList();
2017-08-10 23:09:41 +08:00
if (oldTable && newTable)
if (*oldTable == *newTable)
2019-02-16 21:36:38 +08:00
return QStringList();
2016-05-12 14:08:58 +08:00
2017-08-10 23:09:41 +08:00
if (!newTable)
2020-07-30 21:11:45 +08:00
return QStringList() << (QStringLiteral("DROP TABLE ") + oldTable->name());
2016-05-12 14:08:58 +08:00
2018-02-24 23:43:15 +08:00
QList<QString> fieldNames;
QList<QString> relations;
2016-05-12 14:08:58 +08:00
2018-02-24 23:43:15 +08:00
if (oldTable) {
2021-03-14 16:42:04 +08:00
Q_FOREACH (FieldModel *f, oldTable->fields())
2018-02-24 23:43:15 +08:00
if (!fieldNames.contains(f->name))
fieldNames.append(f->name);
2021-03-14 16:42:04 +08:00
Q_FOREACH (RelationModel *r, oldTable->foreignKeys())
2018-02-24 23:43:15 +08:00
if (!relations.contains(r->localColumn))
relations.append(r->localColumn);
}
2016-05-12 14:08:58 +08:00
2021-03-14 16:42:04 +08:00
Q_FOREACH (FieldModel *f, newTable->fields())
2018-02-24 23:43:15 +08:00
if (!fieldNames.contains(f->name))
fieldNames.append(f->name);
2021-03-14 16:42:04 +08:00
Q_FOREACH (RelationModel *r, newTable->foreignKeys())
2018-02-24 23:43:15 +08:00
if (!relations.contains(r->localColumn))
relations.append(r->localColumn);
2016-05-12 14:08:58 +08:00
QStringList columnSql;
2021-03-14 16:42:04 +08:00
Q_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);
2019-02-16 21:36:38 +08:00
if (!buffer.isEmpty())
2016-05-12 14:08:58 +08:00
columnSql << buffer;
2017-08-10 23:09:41 +08:00
} else {
2019-02-07 23:52:57 +08:00
QString declare = fieldDeclare(newField);
if (declare.isEmpty())
2019-02-16 21:36:38 +08:00
return QStringList() << declare;
2019-02-07 23:52:57 +08:00
columnSql << declare;
2016-05-12 14:08:58 +08:00
}
}
2021-03-14 16:42:04 +08:00
// Q_FOREACH (QString fieldName, relations) {
2018-02-24 23:43:15 +08:00
// RelationModel *newRelation = newTable->foregionKeyByField(fieldName);
// if (oldTable) {
// RelationModel *oldRelation = oldTable->foregionKeyByField(fieldName);
// QString buffer = diff(oldRelation, newRelation);
// if (!buffer.isNull())
// columnSql << buffer;
// } else {
// columnSql << relationDeclare(newRelation);
// }
// }
2016-05-12 14:08:58 +08:00
QString sql;
2017-08-10 23:09:41 +08:00
if (oldTable) {
2020-07-30 21:11:45 +08:00
sql = QStringLiteral("ALTER TABLE %1 \n%2")
2020-07-29 22:11:19 +08:00
.arg(newTable->name(), columnSql.join(QStringLiteral(",\n")));
2017-08-10 23:09:41 +08:00
} else {
2019-01-28 15:53:34 +08:00
if (!newTable->primaryKey().isNull()) {
QString pkCon = primaryKeyConstraint(newTable);
if (!pkCon.isEmpty())
columnSql << pkCon;
2019-03-02 23:51:43 +08:00
columnSql << constraints(newTable);
2019-01-28 15:53:34 +08:00
}
2016-05-12 14:08:58 +08:00
2020-07-30 21:11:45 +08:00
sql = QStringLiteral("CREATE TABLE %1 \n(%2)")
2020-07-29 22:11:19 +08:00
.arg(newTable->name(), columnSql.join(QStringLiteral(",\n")));
2019-02-16 21:36:38 +08:00
2016-05-12 14:08:58 +08:00
}
2019-02-16 21:36:38 +08:00
return QStringList() << sql;
2016-05-12 14:08:58 +08:00
}
2020-08-06 23:19:27 +08:00
QStringList AbstractSqlGenerator::diffRelation(TableModel *oldTable, TableModel *newTable)
2018-02-24 23:43:15 +08:00
{
2019-02-16 21:36:38 +08:00
QStringList ret;
2018-02-24 23:43:15 +08:00
if (!newTable)
2019-02-16 21:36:38 +08:00
return ret;
2018-02-24 23:43:15 +08:00
QList<QString> relations;
2020-07-29 22:11:19 +08:00
if (oldTable) {
2021-03-14 16:42:04 +08:00
Q_FOREACH (RelationModel *r, oldTable->foreignKeys())
2018-02-24 23:43:15 +08:00
if (!relations.contains(r->localColumn))
relations.append(r->localColumn);
2020-07-29 22:11:19 +08:00
}
2018-02-24 23:43:15 +08:00
2021-03-14 16:42:04 +08:00
Q_FOREACH (RelationModel *r, newTable->foreignKeys())
2018-02-24 23:43:15 +08:00
if (!relations.contains(r->localColumn))
relations.append(r->localColumn);
QStringList columnSql;
2021-03-14 16:42:04 +08:00
Q_FOREACH (QString fieldName, relations) {
2019-06-19 17:36:49 +08:00
RelationModel *newRelation = newTable->foreignKeyByField(fieldName);
2019-01-09 23:49:50 +08:00
RelationModel *oldRelation = nullptr;
2018-02-24 23:43:15 +08:00
if (oldTable)
2019-06-19 17:36:49 +08:00
oldRelation = oldTable->foreignKeyByField(fieldName);
2018-02-24 23:43:15 +08:00
2019-02-16 21:36:38 +08:00
QStringList buffer = diff(oldRelation, newRelation);
if (!buffer.isEmpty())
columnSql << buffer.at(0);
2018-02-24 23:43:15 +08:00
}
if (columnSql.count())
2020-07-29 22:11:19 +08:00
ret.append(QStringLiteral("ALTER TABLE ") + newTable->name()
+ QStringLiteral("\n")
+ columnSql.join(QStringLiteral(",\n")));
2018-02-24 23:43:15 +08:00
2019-02-16 21:36:38 +08:00
return ret;
2018-02-24 23:43:15 +08:00
}
2020-08-06 23:19:27 +08:00
QStringList AbstractSqlGenerator::diff(RelationModel *oldRel, RelationModel *newRel)
2018-02-24 23:43:15 +08:00
{
2019-02-16 21:36:38 +08:00
QStringList ret;
2018-02-24 23:43:15 +08:00
/*
CONSTRAINT FK_PersonOrder FOREIGN KEY (PersonID)
REFERENCES Persons(PersonID)
ADD CONSTRAINT FK_%1 FOREIGN KEY (%1) REFERENCES %2(%3)
return QString("ADD CONSTRAINT FK_%1 FOREIGN KEY (%1) "
"REFERENCES %2(%3)")
.arg(newRelation->localColumn)
.arg(newRelation->masterTable->name())
.arg(newRelation->foreignColumn);
*/
if (!oldRel)
2020-07-30 21:11:45 +08:00
ret.append(QStringLiteral("ADD CONSTRAINT FK_%1 FOREIGN KEY (%1) "
2018-02-24 23:43:15 +08:00
"REFERENCES %2(%3)")
2019-02-10 22:11:22 +08:00
.arg(newRel->localColumn, newRel->masterTable->name(),
2019-02-16 21:36:38 +08:00
newRel->foreignColumn));
2018-02-24 23:43:15 +08:00
if (!newRel)
2020-07-30 21:11:45 +08:00
ret.append(QStringLiteral("ADD CONSTRAINT FK_%1 FOREIGN KEY (%1) "
2018-02-24 23:43:15 +08:00
"REFERENCES %2(%3)")
2019-02-10 22:11:22 +08:00
.arg(oldRel->localColumn, oldRel->masterTable->name(),
2019-02-16 21:36:38 +08:00
oldRel->foreignColumn));
2018-02-24 23:43:15 +08:00
// if (*oldRel == *newRel)
2019-02-16 21:36:38 +08:00
return ret;
2018-02-24 23:43:15 +08:00
}
2020-08-06 23:19:27 +08:00
QString AbstractSqlGenerator::join(const QString &mainTable,
2019-02-10 22:11:22 +08:00
const QList<RelationModel*> &list,
2018-01-13 23:59:55 +08:00
QStringList *order)
{
QString ret = mainTable;
QList<RelationModel*>::const_iterator i;
for (i = list.begin(); i != list.end(); ++i) {
if ((*i)->masterTable->name() == mainTable) {
2020-07-30 21:11:45 +08:00
ret.append(QStringLiteral(" INNER JOIN %3 ON %1.%2 = %3.%4")
2019-02-10 22:11:22 +08:00
.arg((*i)->masterTable->name(),
(*i)->masterTable->primaryKey(),
(*i)->slaveTable->name(),
(*i)->localColumn));
2018-01-13 23:59:55 +08:00
if (order != Q_NULLPTR)
2020-07-30 21:11:45 +08:00
order->append((*i)->slaveTable->name() + QStringLiteral(".")
+ (*i)->slaveTable->primaryKey());
2018-01-13 23:59:55 +08:00
} else {
2020-07-30 21:11:45 +08:00
ret.append(QStringLiteral(" INNER JOIN %3 ON %1.%2 = %3.%4")
2019-02-10 22:11:22 +08:00
.arg(mainTable,
(*i)->localColumn,
(*i)->masterTable->name(),
(*i)->masterTable->primaryKey()));
2018-01-13 23:59:55 +08:00
if (order != Q_NULLPTR)
2020-07-30 23:05:11 +08:00
order->append((*i)->masterTable->name() + QStringLiteral(".")
+ (*i)->masterTable->primaryKey());
2018-01-13 23:59:55 +08:00
}
}
return ret;
}
2020-08-06 23:19:27 +08:00
QString AbstractSqlGenerator::join(const QStringList &list, QStringList *order)
2018-01-10 01:32:28 +08:00
{
2018-01-12 00:14:29 +08:00
//TODO: reorder list first!
//TODO: make this ungly code better and bugless :-)
/*
* Known issues:
2018-02-24 23:43:15 +08:00
* Support only near joins, far supports with medium table finding not support yet
*/
2018-01-10 01:32:28 +08:00
if (!list.count())
return QString();
2018-01-10 01:32:28 +08:00
if (list.count() == 1)
2020-07-30 21:11:45 +08:00
return QStringLiteral("[")
+ list.first()
+ QStringLiteral("]");
2018-01-10 01:32:28 +08:00
DatabaseModel model = _database->model();
QStringList clone = list;
QString mainTable = clone.takeFirst();
2020-07-30 21:11:45 +08:00
QString ret = QStringLiteral("[")
+ mainTable
+ QStringLiteral("]");
2018-01-10 01:32:28 +08:00
do {
2018-01-12 00:14:29 +08:00
if (!clone.count())
break;
QString table = clone.first();// model.tableByClassName(clone.first())->name();
RelationModel *rel = model.relationByClassNames(mainTable, clone.first());
2018-01-10 01:32:28 +08:00
if (rel) {
//mainTable is master of table
2020-07-30 21:11:45 +08:00
ret.append(QStringLiteral(" INNER JOIN [%1] ON %4.%2 = %1.%3")
2019-02-10 22:11:22 +08:00
.arg(table, rel->masterTable->primaryKey(),
rel->localColumn, mainTable));
2018-01-11 00:18:49 +08:00
if (order != Q_NULLPTR)
2020-07-30 23:05:11 +08:00
order->append(mainTable + QStringLiteral(".")
+ rel->masterTable->primaryKey());
2018-01-11 00:18:49 +08:00
} else{
2018-01-12 00:14:29 +08:00
rel = model.relationByClassNames(clone.first(), mainTable);
if (rel) {
// table is master of mainTable
2020-07-30 21:11:45 +08:00
ret.append(QStringLiteral(" INNER JOIN [%1] ON %4.%2 = %1.%3")
2019-02-10 22:11:22 +08:00
.arg(table, rel->localColumn,
rel->masterTable->primaryKey(), mainTable));
2018-01-11 00:18:49 +08:00
if (order != Q_NULLPTR)
2020-07-30 23:05:11 +08:00
order->append(mainTable + QStringLiteral(".")
+ rel->localColumn);
2018-01-11 00:18:49 +08:00
} else {
2018-01-15 22:20:26 +08:00
// qInfo("Relation for %s and %s not exists",
// qPrintable(table), qPrintable(mainTable));
}
2018-01-10 01:32:28 +08:00
}
2018-01-12 00:14:29 +08:00
clone.takeFirst();
2018-01-10 01:32:28 +08:00
} while (clone.count());
return ret;
}
2020-08-06 23:19:27 +08:00
QString AbstractSqlGenerator::insertRecord(Table *t, QString tableName)
2016-05-12 14:08:58 +08:00
{
QString sql = QString();
auto model = _database->model().tableByName(tableName);
2019-06-06 21:00:03 +08:00
QString key = model->isPrimaryKeyAutoIncrement() ? model->primaryKey() : QString();
2018-07-12 14:47:41 +08:00
2016-05-12 14:08:58 +08:00
QStringList values;
2016-06-05 20:22:26 +08:00
QSet<QString> props = t->changedProperties();
2019-06-22 20:48:35 +08:00
QString changedPropertiesText = QString();
for (auto &f : props) {
2019-06-22 20:48:35 +08:00
if (f == key)
continue;
values.append(escapeValue(t->property(f.toLatin1().data())));
2020-07-30 21:11:45 +08:00
if (changedPropertiesText != QStringLiteral(""))
changedPropertiesText.append(QStringLiteral(", "));
2019-06-22 20:48:35 +08:00
changedPropertiesText.append(f);
2016-06-05 20:22:26 +08:00
}
2020-07-30 21:11:45 +08:00
sql = QStringLiteral("INSERT INTO %1 (%2) VALUES (%3)")
.arg(tableName, changedPropertiesText, values.join(QStringLiteral(", ")));
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;
}
2020-08-06 23:19:27 +08:00
QString AbstractSqlGenerator::updateRecord(Table *t, QString tableName)
2016-05-12 14:08:58 +08:00
{
QString sql = QString();
2019-06-06 22:08:11 +08:00
auto model = _database->model().tableByName(tableName);
QString key = model->primaryKey();
2016-05-12 14:08:58 +08:00
QStringList values;
for (auto &f : t->changedProperties())
2017-08-10 23:09:41 +08:00
if (f != key)
values.append(f + QStringLiteral("=")
+ escapeValue(t->property(f.toLatin1().data())));
2020-07-30 21:11:45 +08:00
sql = QStringLiteral("UPDATE %1 SET %2 WHERE %3=%4")
.arg(tableName,
values.join(QStringLiteral(", ")),
key,
t->property(key.toUtf8().data()).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;
}
2020-08-06 23:19:27 +08:00
QString AbstractSqlGenerator::deleteRecord(Table *t, QString tableName)
2016-05-12 14:08:58 +08:00
{
2019-06-06 22:08:11 +08:00
auto model = _database->model().tableByName(tableName);
QString key = model->primaryKey();
2020-07-30 21:11:45 +08:00
QString sql = QStringLiteral("DELETE FROM %1 WHERE %2='%3'")
2019-06-06 22:08:11 +08:00
.arg(tableName, key, t->property(key.toUtf8().data()).toString());
2017-08-17 00:02:33 +08:00
replaceTableNames(sql);
return sql;
2016-05-12 14:08:58 +08:00
}
2020-08-06 23:19:27 +08:00
QString AbstractSqlGenerator::agregateText(const AgregateType &t,
2017-08-10 23:09:41 +08:00
const QString &arg) const
2016-06-05 20:22:26 +08:00
{
switch (t) {
case Min:
2020-07-30 21:11:45 +08:00
return QStringLiteral("MIN(") + arg + QStringLiteral(")");
2016-06-05 20:22:26 +08:00
case Max:
2020-07-30 21:11:45 +08:00
return QStringLiteral("MAX(") + arg + QStringLiteral(")");
2016-06-05 20:22:26 +08:00
case Average:
2020-07-30 21:11:45 +08:00
return QStringLiteral("AVG(") + arg + QStringLiteral(")");
2016-06-05 20:22:26 +08:00
case Count:
2020-07-30 21:11:45 +08:00
return QStringLiteral("COUNT(") + arg + QStringLiteral(")");
2016-06-05 20:22:26 +08:00
case Sum:
2020-07-30 21:11:45 +08:00
return QStringLiteral("SUM(") + arg + QStringLiteral(")");
case SingleField:
return arg;
2016-06-05 20:22:26 +08:00
}
2019-02-07 23:52:57 +08:00
return QString(); // never reach
2016-06-05 20:22:26 +08:00
}
2020-08-06 23:19:27 +08:00
QString AbstractSqlGenerator::fromTableText(const QString &tableName,
2017-08-10 23:09:41 +08:00
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();
2020-07-30 21:11:45 +08:00
tableNameText = QStringLiteral("%1 INNER JOIN %2 ON (%1.%3 = %2.%4)")
2019-02-10 22:11:22 +08:00
.arg(tableName, joinTableName,
pk, rel->localColumn);
2020-07-30 23:05:11 +08:00
orderBy = tableName + QStringLiteral(".") + pk;
2017-08-10 23:09:41 +08:00
} else {
qWarning("Relation between table %s and class %s (%s) not exists!",
qPrintable(tableName),
qPrintable(joinClassName),
2020-07-30 21:11:45 +08:00
qPrintable(joinTableName.isNull() ? QStringLiteral("NULL") : joinTableName));
joinClassName = QString();
2016-06-05 20:22:26 +08:00
}
}
return tableNameText;
}
2020-08-06 23:19:27 +08:00
QString AbstractSqlGenerator::deleteRecords(const QString &tableName, const QString &where)
2016-05-12 14:08:58 +08:00
{
2020-07-30 21:11:45 +08:00
QString sql = QStringLiteral("DELETE FROM ") + tableName;
if (!where.isEmpty())
sql.append(QStringLiteral(" WHERE ") + where);
2017-08-09 21:19:35 +08:00
replaceTableNames(sql);
2016-05-12 14:08:58 +08:00
return sql;
}
2020-08-06 23:19:27 +08:00
QString AbstractSqlGenerator::selectCommand(const QString &tableName,
2018-02-17 23:44:39 +08:00
const PhraseList &fields,
const ConditionalPhrase &where,
const PhraseList &order,
2019-02-10 22:11:22 +08:00
const QList<RelationModel*> &joins,
2018-02-17 23:44:39 +08:00
const int skip,
const int take)
2016-05-21 16:09:03 +08:00
{
Q_UNUSED(skip)
Q_UNUSED(take)
2018-02-17 23:44:39 +08:00
QString selectText;
2017-09-10 22:18:20 +08:00
2018-10-15 22:34:50 +08:00
if (fields.data.count() == 0) {
QSet<TableModel*> tables;
tables.insert(_database->model().tableByName(tableName));
2021-03-14 16:42:04 +08:00
Q_FOREACH (RelationModel *rel, joins)
tables << rel->masterTable << rel->slaveTable;
selectText = QString();
2021-03-14 16:42:04 +08:00
Q_FOREACH (TableModel *t, tables) {
2018-02-17 23:44:39 +08:00
if (!selectText.isEmpty())
2020-07-30 21:11:45 +08:00
selectText.append(QStringLiteral(", "));
2018-02-17 23:44:39 +08:00
selectText.append(recordsPhrase(t));
2018-01-12 00:14:29 +08:00
}
2018-02-17 23:44:39 +08:00
} else {
selectText = createFieldPhrase(fields);
2018-01-12 00:14:29 +08:00
}
2016-05-21 16:09:03 +08:00
2018-02-17 23:44:39 +08:00
QStringList joinedOrders;
QString orderText = createOrderPhrase(order);
QString whereText = createConditionalPhrase(where.data);
QString fromText = join(tableName, joins, &joinedOrders);
2020-07-30 21:11:45 +08:00
QString sql = QStringLiteral("SELECT ") + selectText
+ QStringLiteral(" FROM ") + fromText;
2016-05-21 16:09:03 +08:00
2020-08-12 20:32:06 +08:00
if (!whereText.isEmpty())
2020-07-30 21:11:45 +08:00
sql.append(QStringLiteral(" WHERE ") + whereText);
2020-08-12 20:32:06 +08:00
if (!orderText.isEmpty())
2020-07-30 21:11:45 +08:00
sql.append(QStringLiteral(" ORDER BY ") + orderText);
2019-06-06 22:08:11 +08:00
// for (int i = 0; i < _database->model().count(); i++)
// sql = sql.replace(_database->model().at(i)->className() + ".",
// _database->model().at(i)->name() + ".");
2018-02-21 23:41:45 +08:00
appendSkipTake(sql, skip, take);
2017-08-09 21:19:35 +08:00
replaceTableNames(sql);
2020-07-30 21:11:45 +08:00
return sql + QStringLiteral(" ");
}
2020-08-06 23:19:27 +08:00
QString AbstractSqlGenerator::selectCommand(const QString &tableName,
const AbstractSqlGenerator::AgregateType &t,
2018-02-17 23:44:39 +08:00
const QString &agregateArg,
const ConditionalPhrase &where,
const QList<RelationModel *> &joins,
const int skip,
const int take)
2016-05-24 14:47:37 +08:00
{
2018-02-17 23:44:39 +08:00
QStringList joinedOrders;
QString selectText = agregateText(t, agregateArg);
QString whereText = createConditionalPhrase(where.data);
QString fromText = join(tableName, joins, &joinedOrders);
2017-08-10 23:09:41 +08:00
2020-07-30 21:11:45 +08:00
QString sql = QStringLiteral("SELECT ") + selectText
+ QStringLiteral(" FROM ") + fromText;
2016-06-05 20:22:26 +08:00
2020-08-12 20:32:06 +08:00
if (!whereText.isEmpty())
2020-07-30 21:11:45 +08:00
sql.append(QStringLiteral(" WHERE ") + whereText);
2016-05-24 14:47:37 +08:00
2018-02-17 23:44:39 +08:00
for (int i = 0; i < _database->model().count(); i++)
2020-07-30 21:11:45 +08:00
sql = sql.replace(_database->model().at(i)->className() + QStringLiteral("."),
_database->model().at(i)->name() + QStringLiteral("."));
2016-05-24 14:47:37 +08:00
2018-02-21 23:41:45 +08:00
appendSkipTake(sql, skip, take);
2018-02-17 23:44:39 +08:00
replaceTableNames(sql);
2017-09-10 22:18:20 +08:00
2020-07-30 21:11:45 +08:00
return sql + QStringLiteral(" ");
2017-08-09 21:19:35 +08:00
}
2020-08-06 23:19:27 +08:00
QString AbstractSqlGenerator::deleteCommand(const QString &tableName,
2018-02-17 23:44:39 +08:00
const ConditionalPhrase &where)
2016-05-24 14:47:37 +08:00
{
2020-07-30 21:11:45 +08:00
QString command = QStringLiteral("DELETE FROM ") + tableName;
2018-02-17 23:44:39 +08:00
QString whereText = createConditionalPhrase(where.data);
2016-06-05 20:22:26 +08:00
2020-07-30 21:11:45 +08:00
if (!whereText.isEmpty())
command.append(QStringLiteral(" WHERE ") + whereText);
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++)
2020-07-30 21:11:45 +08:00
command = command.replace(_database->model().at(i)->className() + QStringLiteral("."),
_database->model().at(i)->name() + QStringLiteral("."));
2017-08-09 21:19:35 +08:00
replaceTableNames(command);
2016-05-24 14:47:37 +08:00
return command;
}
2020-08-06 23:19:27 +08:00
QString AbstractSqlGenerator::updateCommand(const QString &tableName,
2018-02-17 23:44:39 +08:00
const AssignmentPhraseList &assigments,
const ConditionalPhrase &where)
2017-05-31 00:19:37 +08:00
{
QString assigmentTexts = QString();
2021-03-14 16:42:04 +08:00
Q_FOREACH (PhraseData *d, assigments.data) {
2020-07-30 21:11:45 +08:00
if (assigmentTexts != QStringLiteral(""))
assigmentTexts.append(QStringLiteral(", "));
2018-02-17 23:44:39 +08:00
assigmentTexts.append(createConditionalPhrase(d));
}
QString whereText = createConditionalPhrase(where.data);
2017-05-31 00:19:37 +08:00
2020-07-30 21:11:45 +08:00
QString sql = QStringLiteral("UPDATE ") + tableName
+ QStringLiteral(" SET ") + assigmentTexts;
2017-05-31 00:19:37 +08:00
2020-07-30 21:11:45 +08:00
if (!whereText.isEmpty())
sql.append(QStringLiteral(" WHERE ") + whereText);
2017-05-31 00:19:37 +08:00
2017-08-10 23:09:41 +08:00
for (int i = 0; i < _database->model().count(); i++)
2020-07-30 21:11:45 +08:00
sql = sql.replace(_database->model().at(i)->className() + QStringLiteral("."),
_database->model().at(i)->name() + QStringLiteral("."));
2017-08-10 23:09:41 +08:00
2017-09-10 22:18:20 +08:00
removeTableNames(sql);
2017-05-31 00:19:37 +08:00
return sql;
}
2020-08-06 23:19:27 +08:00
QString AbstractSqlGenerator::insertCommand(const QString &tableName, const AssignmentPhraseList &assigments)
2018-10-15 22:34:50 +08:00
{
QString fieldNames;
QString values;
2021-03-14 16:42:04 +08:00
Q_FOREACH (PhraseData *d, assigments.data) {
2020-07-30 21:11:45 +08:00
if (!fieldNames.isEmpty())
fieldNames.append(QStringLiteral(", "));
2018-10-15 22:34:50 +08:00
2020-07-30 21:11:45 +08:00
if (!values.isEmpty())
values.append(QStringLiteral(", "));
2018-10-15 22:34:50 +08:00
2020-07-30 21:11:45 +08:00
fieldNames.append(QString::fromUtf8(d->left->fieldName));
2018-10-15 22:34:50 +08:00
values.append(escapeValue(d->operand));
}
2020-07-30 21:11:45 +08:00
return QStringLiteral("INSERT INTO %1 (%2) VALUES (%3);")
2019-02-10 22:11:22 +08:00
.arg(tableName, fieldNames, values);
2018-10-15 22:34:50 +08:00
}
2018-02-17 23:44:39 +08:00
//QString SqlGeneratorBase::selectCommand(SqlGeneratorBase::AgregateType t,
// QString agregateArg,
// QString tableName,
// QList<WherePhrase> &wheres,
// QList<WherePhrase> &orders,
// QList<RelationModel*> joins,
// int skip, int take)
//{
// Q_UNUSED(take)
// Q_UNUSED(skip)
2018-02-17 23:44:39 +08:00
// QStringList joinedOrders;
// QString select = agregateText(t, agregateArg);
// //TODO: temporatory disabled
// if (t == SelectAll) {
// QSet<TableModel*> tables;
// tables.insert(_database->model().tableByName(tableName));
2021-03-14 16:42:04 +08:00
// Q_FOREACH (RelationModel *rel, joins)
2018-02-17 23:44:39 +08:00
// tables << rel->masterTable << rel->slaveTable;
// select = "";
2021-03-14 16:42:04 +08:00
// Q_FOREACH (TableModel *t, tables) {
2018-02-17 23:44:39 +08:00
// if (!select.isEmpty())
// select.append(", ");
// select.append(recordsPhrase(t));
// }
// }
// QString from = join(tableName, joins, &joinedOrders);
// QString where = createWhere(wheres);
// QString orderText = joinedOrders.join(", ");
2021-03-14 16:42:04 +08:00
// Q_FOREACH (WherePhrase p, orders) {
2018-02-17 23:44:39 +08:00
// if (orderText != "")
// orderText.append(", ");
// orderText.append(phraseOrder(p.data()));
// }
// QString sql = "SELECT " + select + " FROM " + from;
// if (where != "")
// sql.append(" WHERE " + where);
// if (orderText != "")
// sql.append(" ORDER BY " + orderText);
// for (int i = 0; i < _database->model().count(); i++)
// sql = sql.replace(_database->model().at(i)->className() + ".",
// _database->model().at(i)->name() + ".");
// replaceTableNames(sql);
// return sql + " ";
//}
//QString SqlGeneratorBase::createWhere(QList<WherePhrase> &wheres)
//{
// QString whereText = "";
2021-03-14 16:42:04 +08:00
// Q_FOREACH (WherePhrase w, wheres) {
2018-02-17 23:44:39 +08:00
// if (whereText != "")
// whereText.append(" AND ");
// whereText.append(phrase(w.data()));
// }
// return whereText;
//}
2020-08-06 23:19:27 +08:00
void AbstractSqlGenerator::replaceTableNames(QString &command)
2018-02-17 23:44:39 +08:00
{
2021-03-14 16:42:04 +08:00
Q_FOREACH (TableModel *m, _database->model())
2018-02-17 23:44:39 +08:00
command = command
2020-07-30 21:11:45 +08:00
.replace(QStringLiteral("[") + m->className()
+ QStringLiteral("]"), m->name());
2018-02-17 23:44:39 +08:00
}
2020-08-06 23:19:27 +08:00
void AbstractSqlGenerator::removeTableNames(QString &command)
2018-02-17 23:44:39 +08:00
{
2021-03-14 16:42:04 +08:00
Q_FOREACH (TableModel *m, _database->model())
2020-07-30 21:11:45 +08:00
command = command.replace(QStringLiteral("[")
+ m->className()
+ QStringLiteral("]."), QStringLiteral(""));
2018-02-17 23:44:39 +08:00
}
2020-08-06 23:19:27 +08:00
QString AbstractSqlGenerator::dateTimePartName(const PhraseData::Condition &op) const
2019-07-06 22:08:40 +08:00
{
switch (op) {
2019-07-22 15:18:11 +08:00
case PhraseData::DatePartYear:
2019-07-07 15:50:49 +08:00
case PhraseData::AddYears:
case PhraseData::AddYearsDateTime:
2020-07-30 21:11:45 +08:00
return QStringLiteral("YEAR");
2019-07-22 15:18:11 +08:00
case PhraseData::DatePartMonth:
2019-07-07 15:50:49 +08:00
case PhraseData::AddMonths:
case PhraseData::AddMonthsDateTime:
2020-07-30 21:11:45 +08:00
return QStringLiteral("MONTH");
2019-07-22 15:18:11 +08:00
case PhraseData::DatePartDay:
2019-07-07 15:50:49 +08:00
case PhraseData::AddDays:
case PhraseData::AddDaysDateTime:
2020-07-30 21:11:45 +08:00
return QStringLiteral("DAY");
2019-07-22 15:18:11 +08:00
case PhraseData::DatePartHour:
2019-07-07 15:50:49 +08:00
case PhraseData::AddHours:
case PhraseData::AddHoursDateTime:
2020-07-30 21:11:45 +08:00
return QStringLiteral("HOUR");
2019-07-22 15:18:11 +08:00
case PhraseData::DatePartMinute:
2019-07-07 15:50:49 +08:00
case PhraseData::AddMinutes:
case PhraseData::AddMinutesDateTime:
2020-07-30 21:11:45 +08:00
return QStringLiteral("MINUTE");
2019-07-22 15:18:11 +08:00
case PhraseData::DatePartSecond:
2019-07-07 15:50:49 +08:00
case PhraseData::AddSeconds:
case PhraseData::AddSecondsDateTime:
2020-07-30 21:11:45 +08:00
return QStringLiteral("SECOND");
2019-07-21 23:28:20 +08:00
default:
break;
2019-07-06 22:08:40 +08:00
}
return QString();
}
2018-02-17 23:44:39 +08:00
//QString SqlGeneratorBase::deleteCommand(QList<WherePhrase> &wheres,
// QString tableName)
//{
// 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() + ".");
// replaceTableNames(command);
// return command;
//}
//QString SqlGeneratorBase::updateCommand(WherePhrase &phrase,
// QList<WherePhrase> &wheres,
// QString tableName)
//{
// QString p = this->phrase(phrase.data());
// QString where = createWhere(wheres);
// QString sql = "UPDATE " + tableName + " SET " + p;
// if (where != "")
// sql.append(" WHERE " + where);
// for (int i = 0; i < _database->model().count(); i++)
// sql = sql.replace(_database->model().at(i)->className() + ".",
// _database->model().at(i)->name() + ".");
// removeTableNames(sql);
// return sql;
//}
2020-08-06 23:19:27 +08:00
QString AbstractSqlGenerator::escapeValue(const QVariant &v) const
2016-06-05 20:22:26 +08:00
{
2019-02-08 17:11:53 +08:00
if (v.type() == QVariant::String && v.toString().isEmpty())
2020-07-30 21:11:45 +08:00
return QStringLiteral("''");
2019-02-08 17:11:53 +08:00
if (v.type() == QVariant::List) {
auto list = v.toList();
QStringList ret;
2021-03-14 16:42:04 +08:00
Q_FOREACH (QVariant vi, list) {
ret.append(QStringLiteral("'")
+ _serializer->serialize(vi)
+ QStringLiteral("'"));
}
return QStringLiteral("(")
+ ret.join(QStringLiteral(", "))
+ QStringLiteral(")");
}
2019-02-10 17:35:35 +08:00
QString serialized = _serializer->serialize(v);
2019-02-08 16:39:24 +08:00
if (serialized.isEmpty()) {
qWarning("No field escape rule for: %s", v.typeName());
return QString();
}
2019-04-09 15:25:19 +08:00
2019-06-18 21:40:40 +08:00
2020-07-30 21:11:45 +08:00
return QStringLiteral("'") + serialized + QStringLiteral("'");
2016-06-05 20:22:26 +08:00
}
2020-08-06 23:19:27 +08:00
QVariant AbstractSqlGenerator::unescapeValue(const QMetaType::Type &type,
2017-08-10 23:09:41 +08:00
const QVariant &dbValue)
2017-06-12 00:50:43 +08:00
{
2019-02-10 17:35:35 +08:00
return _serializer->deserialize(dbValue.toString(), type);
2017-06-12 00:50:43 +08:00
}
2020-08-06 23:19:27 +08:00
QString AbstractSqlGenerator::phrase(const PhraseData *d) const
2016-06-05 20:22:26 +08:00
{
QString ret = QString();
2016-06-05 20:22:26 +08:00
2017-08-10 23:09:41 +08:00
switch (d->type) {
2016-06-05 20:22:26 +08:00
case PhraseData::Field:
2018-02-17 23:44:39 +08:00
ret = d->toString();
2017-05-31 02:32:12 +08:00
break;
case PhraseData::WithVariant:
2020-07-29 22:11:19 +08:00
ret = phrase(d->left)
+ QStringLiteral(" ")
+ operatorString(d->operatorCond)
+ QStringLiteral(" ")
2017-08-10 23:09:41 +08:00
+ escapeValue(d->operand);
2017-05-31 02:32:12 +08:00
break;
case PhraseData::WithOther:
2020-07-30 21:11:45 +08:00
ret = phrase(d->left) + QStringLiteral(" ") + operatorString(d->operatorCond) + QStringLiteral(" ")
2017-08-10 23:09:41 +08:00
+ phrase(d->right);
2017-05-31 02:32:12 +08:00
break;
case PhraseData::WithoutOperand:
2020-07-30 23:05:11 +08:00
ret = phrase(d->left) + QStringLiteral(" ") + operatorString(d->operatorCond);
2017-05-31 02:32:12 +08:00
break;
}
2017-08-10 23:09:41 +08:00
if (d->operatorCond == PhraseData::And || d->operatorCond == PhraseData::Or)
2020-07-30 21:11:45 +08:00
ret = QStringLiteral("(") + ret + QStringLiteral(")");
2017-05-31 02:32:12 +08:00
return ret;
}
2017-08-10 23:09:41 +08:00
QString
2020-08-06 23:19:27 +08:00
AbstractSqlGenerator::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:
2020-07-30 21:11:45 +08:00
return QStringLiteral("=");
2016-06-05 20:22:26 +08:00
case PhraseData::NotEqual:
2020-07-30 21:11:45 +08:00
return QStringLiteral("<>");
2016-06-05 20:22:26 +08:00
case PhraseData::Less:
2020-07-30 21:11:45 +08:00
return QStringLiteral("<");
2016-06-05 20:22:26 +08:00
case PhraseData::Greater:
2020-07-30 21:11:45 +08:00
return QStringLiteral(">");
2016-06-05 20:22:26 +08:00
case PhraseData::LessEqual:
2020-07-30 21:11:45 +08:00
return QStringLiteral("<=");
2016-06-05 20:22:26 +08:00
case PhraseData::GreaterEqual:
2020-07-30 21:11:45 +08:00
return QStringLiteral(">=");
2016-06-05 20:22:26 +08:00
case PhraseData::Null:
2020-07-30 21:11:45 +08:00
return QStringLiteral("IS NULL");
2016-06-05 20:22:26 +08:00
case PhraseData::NotNull:
2020-07-30 21:11:45 +08:00
return QStringLiteral("IS NOT NULL");
2016-06-05 20:22:26 +08:00
case PhraseData::In:
2020-07-30 21:11:45 +08:00
return QStringLiteral("IN");
2016-06-05 20:22:26 +08:00
case PhraseData::NotIn:
2020-07-30 21:11:45 +08:00
return QStringLiteral("NOT IN");
2016-06-05 20:22:26 +08:00
case PhraseData::And:
2020-07-30 21:11:45 +08:00
return QStringLiteral("AND");
2016-06-05 20:22:26 +08:00
case PhraseData::Or:
2020-07-30 21:11:45 +08:00
return QStringLiteral("OR");
2016-06-05 20:22:26 +08:00
case PhraseData::Like:
2020-07-30 21:11:45 +08:00
return QStringLiteral("LIKE");
2016-06-05 20:22:26 +08:00
case PhraseData::NotLike:
2020-07-30 21:11:45 +08:00
return QStringLiteral("NOT LIKE");
2016-06-05 20:22:26 +08:00
case PhraseData::Add:
2020-07-30 21:11:45 +08:00
return QStringLiteral("+");
2016-06-05 20:22:26 +08:00
case PhraseData::Minus:
2020-07-30 21:11:45 +08:00
return QStringLiteral("-");
2016-06-05 20:22:26 +08:00
case PhraseData::Multiple:
2020-07-30 21:11:45 +08:00
return QStringLiteral("*");
2016-06-05 20:22:26 +08:00
case PhraseData::Divide:
2020-07-30 21:11:45 +08:00
return QStringLiteral("/");
2016-06-05 20:22:26 +08:00
2018-02-17 23:44:39 +08:00
// case PhraseData::Set:
2020-07-30 21:11:45 +08:00
// return QStringLiteral("=");
2018-02-17 23:44:39 +08:00
// case PhraseData::Append:
2020-07-30 21:11:45 +08:00
// return QStringLiteral(",");
2018-02-17 23:44:39 +08:00
case PhraseData::Between:
2020-07-30 21:11:45 +08:00
return QStringLiteral("BETWEEN");
2018-02-17 23:44:39 +08:00
case PhraseData::Mod:
2020-07-30 21:11:45 +08:00
return QStringLiteral("MOD");
2018-02-17 23:44:39 +08:00
default:
2019-07-22 15:18:11 +08:00
qDebug() << "Unsupported" << cond;
2020-07-30 21:11:45 +08:00
return QStringLiteral("<FAIL cond> %1").arg(cond);
2018-02-17 23:44:39 +08:00
}
}
2020-08-06 23:19:27 +08:00
void AbstractSqlGenerator::appendSkipTake(QString &sql, int skip, int take)
2018-02-21 23:41:45 +08:00
{
Q_UNUSED(sql)
Q_UNUSED(skip)
Q_UNUSED(take)
2018-02-21 23:41:45 +08:00
}
2018-02-17 23:44:39 +08:00
2020-08-06 23:19:27 +08:00
QString AbstractSqlGenerator::primaryKeyConstraint(const TableModel *table) const
2019-01-28 15:53:34 +08:00
{
2020-07-30 21:11:45 +08:00
return QStringLiteral("CONSTRAINT pk_%1 PRIMARY KEY (%2)")
2019-02-10 22:11:22 +08:00
.arg(table->name(), table->primaryKey());
2019-01-28 15:53:34 +08:00
}
2020-08-06 23:19:27 +08:00
QString AbstractSqlGenerator::createConditionalPhrase(const PhraseData *d) const
2018-02-17 23:44:39 +08:00
{
if (!d)
return QString();
2018-02-17 23:44:39 +08:00
QString ret = QString();
2018-02-17 23:44:39 +08:00
PhraseData::Condition op = d->operatorCond;
//apply not (!)
if (d->isNot) {
if (op < 20)
2019-01-09 23:49:50 +08:00
op = static_cast<PhraseData::Condition>((op + 10) % 20);
2018-02-17 23:44:39 +08:00
}
switch (d->type) {
case PhraseData::Field:
ret = d->toString();
break;
2016-06-05 20:22:26 +08:00
2018-02-17 23:44:39 +08:00
case PhraseData::WithVariant:
2019-07-06 22:08:40 +08:00
/* if (op == PhraseData::AddYears)
2018-02-17 23:44:39 +08:00
ret = QString("DATEADD(year, %1, %2)")
2019-02-10 22:11:22 +08:00
.arg(d->operand.toString(), createConditionalPhrase(d->left));
2018-02-17 23:44:39 +08:00
else if (op == PhraseData::AddMonths)
ret = QString("DATEADD(month, %1, %2)")
2019-02-10 22:11:22 +08:00
.arg(d->operand.toString(), createConditionalPhrase(d->left));
2018-02-26 18:14:36 +08:00
else if (op == PhraseData::AddDays)
2018-02-17 23:44:39 +08:00
ret = QString("DATEADD(day, %1, %2)")
2019-02-10 22:11:22 +08:00
.arg(d->operand.toString(), createConditionalPhrase(d->left));
2018-02-17 23:44:39 +08:00
else if (op == PhraseData::AddHours)
ret = QString("DATEADD(hour, %1, %2)")
2019-02-10 22:11:22 +08:00
.arg(d->operand.toString(), createConditionalPhrase(d->left));
2018-02-17 23:44:39 +08:00
else if (op == PhraseData::AddMinutes)
ret = QString("DATEADD(minute, %1, %2)")
2019-02-10 22:11:22 +08:00
.arg(d->operand.toString(), createConditionalPhrase(d->left));
2018-02-17 23:44:39 +08:00
else if (op == PhraseData::AddSeconds)
ret = QString("DATEADD(second, %1, %2)")
2019-02-10 22:11:22 +08:00
.arg(d->operand.toString(), createConditionalPhrase(d->left));
2019-07-06 22:08:40 +08:00
else */if (op == PhraseData::Between) {
2019-07-02 14:30:49 +08:00
QVariantList list = d->operand.toList();
2020-07-30 21:11:45 +08:00
ret = QStringLiteral("%1 BETWEEN %2 AND %3")
2019-07-02 14:30:49 +08:00
.arg(createConditionalPhrase(d->left), escapeValue(list.at(0)), escapeValue(list.at(1)));
} else if (op == PhraseData::DatePartYear)
2020-07-30 21:11:45 +08:00
ret = QStringLiteral("DATEPART(year, %1)")
2019-02-26 17:49:50 +08:00
.arg(d->operand.toString());
else if (op == PhraseData::DatePartMonth)
2020-07-30 21:11:45 +08:00
ret = QStringLiteral("DATEPART(month, %1)")
2019-02-26 17:49:50 +08:00
.arg(d->operand.toString());
else if (op == PhraseData::DatePartDay)
2020-07-30 21:11:45 +08:00
ret = QStringLiteral("DATEPART(day, %1)")
2019-02-26 17:49:50 +08:00
.arg(d->operand.toString());
else if (op == PhraseData::DatePartHour)
2020-07-30 21:11:45 +08:00
ret = QStringLiteral("DATEPART(hour, %1)")
2019-02-26 17:49:50 +08:00
.arg(d->operand.toString());
else if (op == PhraseData::DatePartMinute)
2020-07-30 21:11:45 +08:00
ret = QStringLiteral("DATEPART(minute, %1)")
2019-02-26 17:49:50 +08:00
.arg(d->operand.toString());
else if (op == PhraseData::DatePartMilisecond)
2020-07-30 21:11:45 +08:00
ret = QStringLiteral("DATEPART(milisecond, %1)")
2019-02-26 17:49:50 +08:00
.arg(d->operand.toString());
2018-02-17 23:44:39 +08:00
else
2020-07-30 21:11:45 +08:00
ret = createConditionalPhrase(d->left) + QStringLiteral(" ")
+ operatorString(op) + QStringLiteral(" ")
+ escapeValue(d->operand);
2018-02-17 23:44:39 +08:00
break;
case PhraseData::WithOther:
2020-07-30 21:11:45 +08:00
ret = createConditionalPhrase(d->left) + QStringLiteral(" ")
+ operatorString(op) + QStringLiteral(" ")
2018-02-17 23:44:39 +08:00
+ createConditionalPhrase(d->right);
break;
case PhraseData::WithoutOperand:
2020-07-30 21:11:45 +08:00
ret = createConditionalPhrase(d->left) + QStringLiteral(" ")
+ operatorString(op);
2018-02-17 23:44:39 +08:00
break;
}
if (d->operatorCond == PhraseData::And || d->operatorCond == PhraseData::Or)
2020-07-30 21:11:45 +08:00
ret = QStringLiteral("(") + ret + QStringLiteral(")");
2018-02-17 23:44:39 +08:00
return ret;
}
2020-08-06 23:19:27 +08:00
QString AbstractSqlGenerator::createOrderPhrase(const PhraseList &ph)
2018-02-17 23:44:39 +08:00
{
QString ret = QString();
2021-03-14 16:42:04 +08:00
Q_FOREACH (const PhraseData *d, ph.data) {
2020-07-30 21:11:45 +08:00
if (!ret.isEmpty())
ret.append(QStringLiteral(", "));
2018-02-17 23:44:39 +08:00
ret.append(d->toString());
if (d->isNot)
2020-07-30 21:11:45 +08:00
ret.append(QStringLiteral(" DESC"));
2018-02-17 23:44:39 +08:00
}
return ret;
}
2020-08-06 23:19:27 +08:00
QString AbstractSqlGenerator::createFieldPhrase(const PhraseList &ph)
2018-02-17 23:44:39 +08:00
{
QString ret = QString();
2021-03-14 16:42:04 +08:00
Q_FOREACH (const PhraseData *d, ph.data) {
2020-07-30 21:11:45 +08:00
if (!ret.isEmpty())
ret.append(QStringLiteral(", "));
2018-02-17 23:44:39 +08:00
ret.append(d->toString());
if (d->isNot)
qDebug() << "Operator ! is ignored in fields phrase";
}
return ret;
}
2020-08-06 23:19:27 +08:00
void AbstractSqlGenerator::createInsertPhrase(const AssignmentPhraseList &ph, QString &fields, QString &values)
2018-02-17 23:44:39 +08:00
{
2021-03-14 16:42:04 +08:00
Q_FOREACH (PhraseData *d, ph.data) {
2020-07-30 21:11:45 +08:00
if (!fields.isEmpty())
fields.append(QStringLiteral(", "));
2018-02-17 23:44:39 +08:00
2020-07-30 21:11:45 +08:00
if (!values.isEmpty())
values.append(QStringLiteral(", "));
2018-02-17 23:44:39 +08:00
switch (d->type) {
case PhraseData::WithVariant:
fields.append(d->left->toString());
values.append(escapeValue(d->operand));
// ret = createConditionalPhrase(d->left->toString()) + " " + operatorString(d->operatorCond) + " "
// + escapeValue(d->operand);
break;
case PhraseData::WithOther:
fields.append(d->left->toString());
values.append(d->right->toString());
break;
case PhraseData::Field:
case PhraseData::WithoutOperand:
qFatal("Invalid insert command");
}
2017-09-10 22:18:20 +08:00
}
2016-06-05 20:22:26 +08:00
}
2017-02-01 18:01:21 +08:00
NUT_END_NAMESPACE