Nut/src/nut/generators/mysqlgenerator.cpp

370 lines
11 KiB
C++

/**************************************************************************
**
** 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 "mysqlgenerator.h"
#include "tablemodel.h"
#include <QtCore/QPoint>
#include <QtCore/QPointF>
#include <QtCore/QTime>
#include <QtCore/QDate>
#include <QtCore/QDateTime>
#ifdef QT_GUI_LIB
# include <QtGui/QPolygon>
# include <QtGui/QPolygonF>
#endif
#include "sqlserializer.h"
NUT_BEGIN_NAMESPACE
MySqlGenerator::MySqlGenerator(Database *parent) : AbstractSqlGenerator(parent)
{
}
QString MySqlGenerator::fieldType(FieldModel *field)
{
QString dbType;
switch (field->type) {
case QMetaType::Bool: return QStringLiteral("BOOLEAN");
case QMetaType::Char:
case QMetaType::QChar: return QStringLiteral("CHAR(1)");
case QMetaType::SChar:
case QMetaType::UChar: return QStringLiteral("TINYINT");
case QMetaType::Short:
case QMetaType::UShort: return QStringLiteral("SMALLINT");
case QMetaType::UInt:
case QMetaType::Int:
dbType = QStringLiteral("INT");
if(field->isAutoIncrement)
dbType += QStringLiteral(" AUTO_INCREMENT");
break;
case QMetaType::Long:
case QMetaType::ULong:
case QMetaType::LongLong:
case QMetaType::ULongLong:
return QStringLiteral("BIGINT");
case QMetaType::Float:
return QStringLiteral("FLOAT");
case QMetaType::Double:
return QStringLiteral("REAL");
case QMetaType::QBitArray: return QStringLiteral("VARBINARY");
case QMetaType::QByteArray: return QStringLiteral("BLOB");
case QMetaType::QDate: return QStringLiteral("DATE");
case QMetaType::QTime: return QStringLiteral("TIME");
case QMetaType::QDateTime: return QStringLiteral("DATETIME");
case QMetaType::QString:
if(field->length)
dbType = QStringLiteral("VARCHAR(%1)").arg(field->length);
else
dbType = QStringLiteral("TEXT");
break;
case QMetaType::QPolygon:
case QMetaType::QPolygonF:
// dbType = "POLYGON";
// break;
case QMetaType::QUuid:
// dbType = "VARCHAR(64)";
// break;
case QMetaType::QPoint:
case QMetaType::QPointF:
// dbType = "POINT";
// break;
case QMetaType::QSize:
case QMetaType::QSizeF:
case QMetaType::QRect:
case QMetaType::QRectF:
case QMetaType::QLine:
case QMetaType::QLineF:
case QMetaType::QColor:
case QMetaType::QUrl:
case QMetaType::QJsonArray:
case QMetaType::QJsonValue:
case QMetaType::QJsonObject:
case QMetaType::QJsonDocument:
case QMetaType::QStringList: return QStringLiteral("TEXT");
default:
qWarning("Type %s::%s(%d) is not supported",
qPrintable(field->name),
QMetaType::typeName(field->type),
field->type);
dbType = QString();
}
// if(field->typeName == QStringLiteral("Nut::DbGeography"))
// dbType = "GEOMETRY";
return dbType;
}
QString MySqlGenerator::escapeValue(const QVariant &v) const
{
if (v.type() == QVariant::Bool)
return v.toBool() ? QStringLiteral("1") : QStringLiteral("0");
if (v.type() == QVariant::Time)
return v.toTime().toString(QStringLiteral("''HH:mm:ss''"));
if (v.type() == QVariant::Date)
return v.toDate().toString(QStringLiteral("''yyyy-MM-dd''"));
if (v.type() == QVariant::DateTime)
return v.toDateTime().toString(QStringLiteral("''yyyy-MM-dd HH:mm:ss''"));
//#ifdef QT_GUI_LIB
// if (v.type() == QVariant::Polygon) {
// QString ret;
// QPoint pt;
// QPolygon pol = v.value<QPolygon>();
// for (int i = 0; i < pol.size(); ++i) {
// pt = pol.at(i);
// if (!ret.isEmpty())
// ret.append(", ");
// ret.append(QString::number(pt.x()) + " " + QString::number(pt.y()));
// }
// return "GeomFromText('POLYGON(" + ret + "))')";
// }
// if (v.type() == QVariant::PolygonF) {
// QString ret;
// QPointF pt;
// QPolygonF pol = v.value<QPolygonF>();
// for (int i = 0; i < pol.size(); ++i) {
// pt = pol.at(i);
// if (!ret.isEmpty())
// ret.append("),(");
// ret.append(QString::number(pt.x()) + " " + QString::number(pt.y()));
// }
// return "GeomFromText('POLYGON(" + ret + "))')";
// }
//#endif
// switch (v.type()) {
// case QMetaType::QPoint: {
// QPoint pt = v.toPoint();
// return QString("GeomFromText('POINT(%1 %2)',0)").arg(pt.x()).arg(pt.y());
// }
// case QMetaType::QPointF: {
// QPointF pt = v.toPointF();
// return QString("GeomFromText('POINT(%1 %2)',0)").arg(pt.x()).arg(pt.y());
// }
// default:
return AbstractSqlGenerator::escapeValue(v);
// }
}
QVariant MySqlGenerator::unescapeValue(const QMetaType::Type &type, const QVariant &dbValue)
{
//#ifdef QT_GUI_LIB
// if (type == QMetaType::QPolygon) {
// qDebug() << "p=" << dbValue;
// QString p;
// QString ref = dbValue.toString();
// QPolygon pol;
// if (!readInsideParentese(ref, p))
// return pol;
// QStringList parts = p.split(",");
// Q_FOREACH (QString v, parts) {
// QList<int> l = _serializer->toListInt(p.trimmed(), " ");
// if (l.count() != 2)
// return QPolygon();
// pol.append(QPoint(l.at(0), l.at(1)));
// }
// return pol;
// }
// if (type == QMetaType::QPolygonF) {
// QString p;
// QString ref = dbValue.toString();
// QPolygonF pol;
// if (!readInsideParentese(ref, p))
// return pol;
// QStringList parts = p.split(",");
// Q_FOREACH (QString v, parts) {
// QList<qreal> l = _serializer->toListReal(p.trimmed(), " ");
// if (l.count() != 2)
// return QPolygonF();
// pol.append(QPointF(l.at(0), l.at(1)));
// }
// return pol;
// }
//#endif
if (type == QMetaType::QDateTime)
return dbValue.toDateTime();
if (type == QMetaType::QTime)
return dbValue.toTime();
if (type == QMetaType::QDate)
return dbValue.toDate();
return AbstractSqlGenerator::unescapeValue(type, dbValue);
}
bool MySqlGenerator::readInsideParentese(QString &text, QString &out)
{
int start = -1;
int end = -1;
int pc = 0;
for (int i = 0; i < text.length(); ++i) {
QChar ch = text.at(i);
if (ch == '(') {
if (start == -1)
start = i;
pc++;
}
if (ch == ')') {
pc--;
if (!pc && end == -1)
end = i;
}
if (start != -1 && end != -1){
out = text.mid(start + 1, end - start - 1);
text = text.mid(end + 1);
return true;
}
}
return false;
}
//QString MySqlGenerator::phrase(const PhraseData *d) const
//{
// if (d->operatorCond == PhraseData::Distance) {
// return QString("ST_Distance(%1, %2)")
// .arg(d->left->text)
// .arg(escapeValue(d->operand.toPointF()));
// }
// return SqlGeneratorBase::phrase(d);
//}
//QString MySqlGenerator::selectCommand(SqlGeneratorBase::AgregateType t,
// QString agregateArg,
// QString tableName,
// QList<WherePhrase> &wheres,
// QList<WherePhrase> &orders,
// QList<RelationModel*> joins,
// int skip, int take)
//{
// QString command = SqlGeneratorBase::selectCommand(t, agregateArg,
// tableName,
// wheres, orders,
// joins, skip, take);
// if (take != -1 && skip != -1)
// command.append(QString(" LIMIT %1 OFFSET %2")
// .arg(take)
// .arg(skip));
// return command;
//}
QString MySqlGenerator::createConditionalPhrase(const PhraseData *d) const
{
if (!d)
return QString();
PhraseData::Condition op = d->operatorCond;
//apply not (!)
if (d->isNot) {
if (op < 20)
op = static_cast<PhraseData::Condition>((op + 10) % 20);
}
if (d->type == PhraseData::WithVariant) {
switch (op) {
case PhraseData::AddYears:
case PhraseData::AddYearsDateTime:
case PhraseData::AddMonths:
case PhraseData::AddMonthsDateTime:
case PhraseData::AddDays:
case PhraseData::AddDaysDateTime:
case PhraseData::AddHours:
case PhraseData::AddHoursDateTime:
case PhraseData::AddMinutes:
case PhraseData::AddMinutesDateTime:
case PhraseData::AddSeconds:
case PhraseData::AddSecondsDateTime:
return QStringLiteral("DATE_ADD(%1, INTERVAL %2 %3)")
.arg(createConditionalPhrase(d->left),
d->operand.toString(),
AbstractSqlGenerator::dateTimePartName(op));
default:
break;
}
}
if (d->type == PhraseData::WithoutOperand) {
switch (op) {
case PhraseData::DatePartYear:
case PhraseData::DatePartMonth:
case PhraseData::DatePartDay:
case PhraseData::DatePartHour:
case PhraseData::DatePartMinute:
case PhraseData::DatePartSecond:
return QStringLiteral("%2(%1)")
.arg(createConditionalPhrase(d->left),
AbstractSqlGenerator::dateTimePartName(op));
default:
break;
}
}
return AbstractSqlGenerator::createConditionalPhrase(d);
}
void MySqlGenerator::appendSkipTake(QString &sql, int skip, int take)
{
if (take > 0 && skip > 0) {
sql.append(QStringLiteral(" LIMIT %1 OFFSET %2")
.arg(take)
.arg(skip));
} else if (take > 0) {
sql.append(QStringLiteral(" LIMIT %1").arg(take));
}
}
QString MySqlGenerator::primaryKeyConstraint(const TableModel *table) const
{
return QStringLiteral("PRIMARY KEY (%1)")
.arg(table->primaryKey());
}
QString MySqlGenerator::escaleFieldName(const QString &fieldName) const
{
return "`" + fieldName + "`";
}
NUT_END_NAMESPACE