wip: date time functions

This commit is contained in:
Hamed Masafi 2019-07-06 18:38:40 +04:30
parent 73c5295f6d
commit f02e409ee2
16 changed files with 300 additions and 7 deletions

View File

@ -290,4 +290,41 @@ bool MySqlGenerator::readInsideParentese(QString &text, QString &out)
// 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) {
if (op == PhraseData::AddYears)
return QString("DATE_ADD(%2, INTERVAL %1 YEAR)")
.arg(d->operand.toString(), createConditionalPhrase(d->left));
else if (op == PhraseData::AddMonths)
return QString("DATE_ADD(%2, INTERVAL %1 MONTH)")
.arg(d->operand.toString(), createConditionalPhrase(d->left));
else if (op == PhraseData::AddDays)
return QString("DATE_ADD(%2, INTERVAL %1 DAY)")
.arg(d->operand.toString(), createConditionalPhrase(d->left));
else if (op == PhraseData::AddHours)
return QString("DATE_ADD(%2, INTERVAL %1 HOUR)")
.arg(d->operand.toString(), createConditionalPhrase(d->left));
else if (op == PhraseData::AddMinutes)
return QString("DATE_ADD(%2, INTERVAL %1 MINUTE)")
.arg(d->operand.toString(), createConditionalPhrase(d->left));
else if (op == PhraseData::AddSeconds)
return QString("DATE_ADD(%2, INTERVAL %1 SECOND)")
.arg(d->operand.toString(), createConditionalPhrase(d->left));
}
return SqlGeneratorBase::createConditionalPhrase(d);
}
NUT_END_NAMESPACE

View File

@ -31,11 +31,12 @@ class MySqlGenerator : public SqlGeneratorBase
public:
explicit MySqlGenerator(Database *parent = 0);
QString fieldType(FieldModel *field);
QString escapeValue(const QVariant &v) const;
QVariant unescapeValue(const QMetaType::Type &type, const QVariant &dbValue);
QString fieldType(FieldModel *field) override;
QString escapeValue(const QVariant &v) const override;
QVariant unescapeValue(const QMetaType::Type &type, const QVariant &dbValue) override;
// QString phrase(const PhraseData *d) const;
// QString selectCommand(AgregateType t, QString agregateArg, QString tableName, QList<WherePhrase> &wheres, QList<WherePhrase> &orders, QList<RelationModel *> joins, int skip, int take);
QString createConditionalPhrase(const PhraseData *d) const override;
private:
bool readInsideParentese(QString &text, QString &out);
};

View File

@ -328,12 +328,38 @@ QString PostgreSqlGenerator::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) {
if (isPostGisType(d->operand.type()) && d->operatorCond == PhraseData::Equal) {
return QString("%1 ~= %2")
.arg(SqlGeneratorBase::createConditionalPhrase(d->left),
escapeValue(d->operand));
}
if (op == PhraseData::AddYears)
return QString("DATEADD(year, %1, %2)")
.arg(d->operand.toString(), createConditionalPhrase(d->left));
else if (op == PhraseData::AddMonths)
return QString("DATEADD(month, %1, %2)")
.arg(d->operand.toString(), createConditionalPhrase(d->left));
else if (op == PhraseData::AddDays)
return QString("DATEADD(day, %1, %2)")
.arg(d->operand.toString(), createConditionalPhrase(d->left));
else if (op == PhraseData::AddHours)
return QString("DATEADD(hour, %1, %2)")
.arg(d->operand.toString(), createConditionalPhrase(d->left));
else if (op == PhraseData::AddMinutes)
return QString("DATEADD(minute, %1, %2)")
.arg(d->operand.toString(), createConditionalPhrase(d->left));
else if (op == PhraseData::AddSeconds)
return QString("DATEADD(second, %1, %2)")
.arg(d->operand.toString(), createConditionalPhrase(d->left));
}
return SqlGeneratorBase::createConditionalPhrase(d);

View File

@ -785,6 +785,19 @@ void SqlGeneratorBase::removeTableNames(QString &command)
command = command.replace("[" + m->className() + "].", "");
}
QString SqlGeneratorBase::dateTimePartName(const PhraseData::Condition &op) const
{
switch (op) {
case PhraseData::AddYears: return "YEAR";
case PhraseData::AddMonths: return "MONTH";
case PhraseData::AddDays: return "DAY";
case PhraseData::AddHours: return "HOUR";
case PhraseData::AddMinutes: return "MINUTE";
case PhraseData::AddSeconds: return "SECOND";
}
return QString();
}
//QString SqlGeneratorBase::deleteCommand(QList<WherePhrase> &wheres,
// QString tableName)
//{
@ -973,7 +986,7 @@ QString SqlGeneratorBase::createConditionalPhrase(const PhraseData *d) const
break;
case PhraseData::WithVariant:
if (op == PhraseData::AddYears)
/* if (op == PhraseData::AddYears)
ret = QString("DATEADD(year, %1, %2)")
.arg(d->operand.toString(), createConditionalPhrase(d->left));
else if (op == PhraseData::AddMonths)
@ -991,7 +1004,7 @@ QString SqlGeneratorBase::createConditionalPhrase(const PhraseData *d) const
else if (op == PhraseData::AddSeconds)
ret = QString("DATEADD(second, %1, %2)")
.arg(d->operand.toString(), createConditionalPhrase(d->left));
else if (op == PhraseData::Between) {
else */if (op == PhraseData::Between) {
QVariantList list = d->operand.toList();
ret = QString("%1 BETWEEN %2 AND %3")
.arg(createConditionalPhrase(d->left), escapeValue(list.at(0)), escapeValue(list.at(1)));

View File

@ -162,6 +162,7 @@ protected:
void replaceTableNames(QString &command);
void removeTableNames(QString &command);
QString dateTimePartName(const PhraseData::Condition &op) const;
};
NUT_END_NAMESPACE

View File

@ -205,4 +205,36 @@ QString SqliteGenerator::primaryKeyConstraint(const TableModel *table) const
// return sql;
}
QString SqliteGenerator::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) {
QString part;
switch (op) {
case PhraseData::AddYears:
case PhraseData::AddMonths:
case PhraseData::AddDays:
case PhraseData::AddHours:
case PhraseData::AddMinutes:
case PhraseData::AddSeconds:
int i = d->operand.toInt();
return QString("DATE(%1,'%2 %3')")
.arg(createConditionalPhrase(d->left),
(i < 0 ? "-" : "+") + QString::number(i),
dateTimePartName(op));
}
}
return SqlGeneratorBase::createConditionalPhrase(d);
}
NUT_END_NAMESPACE

View File

@ -41,6 +41,7 @@ public:
QString primaryKeyConstraint(const TableModel *table) const override;
QStringList diff(TableModel *oldTable, TableModel *newTable) override;
QString createConditionalPhrase(const PhraseData *d) const override;
};
NUT_END_NAMESPACE

View File

@ -61,9 +61,11 @@ int TableSetBase::save(Database *db, bool cleanUp)
|| t->status() == Table::Modified
|| t->status() == Table::Deleted){
rowsAffected += t->save(db);
#ifndef NUT_SHARED_POINTER
if(cleanUp)
#ifndef NUT_SHARED_POINTER
t->deleteLater();
#else
remove(t);
#endif
}
}

View File

@ -8,5 +8,6 @@ SUBDIRS += \
tst_quuid \
tst_generators \
tst_upgrades \
tst_json
tst_json \
tst_datetime

9
test/tst_datetime/db.cpp Normal file
View File

@ -0,0 +1,9 @@
#include "db.h"
#include "sampletable.h"
DB::DB() : Nut::Database (),
m_sampleTables(new Nut::TableSet<SampleTable>(this))
{
}

21
test/tst_datetime/db.h Normal file
View File

@ -0,0 +1,21 @@
#ifndef DB_H
#define DB_H
#include "database.h"
class SampleTable;
class DB : public Nut::Database
{
Q_OBJECT
NUT_DB_VERSION(1)
NUT_DECLARE_TABLE(SampleTable, sampleTables)
public:
DB();
};
Q_DECLARE_METATYPE(DB*)
#endif // DB_H

View File

@ -0,0 +1,6 @@
#include "sampletable.h"
SampleTable::SampleTable(QObject *parent) : Nut::Table (parent)
{
}

View File

@ -0,0 +1,27 @@
#ifndef SAMPLETABLE_H
#define SAMPLETABLE_H
#include <QTime>
#include <QDateTime>
#include <QDate>
#include "table.h"
class SampleTable : public Nut::Table
{
Q_OBJECT
NUT_PRIMARY_AUTO_INCREMENT(id)
NUT_DECLARE_FIELD(int, id, id, setId)
NUT_DECLARE_FIELD(QDate, d, d, setD)
NUT_DECLARE_FIELD(QTime, t, t, setT)
NUT_DECLARE_FIELD(QDateTime, dt, dt, setDT)
public:
Q_INVOKABLE SampleTable(QObject *parent = Q_NULLPTR);
};
Q_DECLARE_METATYPE(SampleTable*)
#endif // SAMPLETABLE_H

View File

@ -0,0 +1,59 @@
#include <QtTest>
#include <QDebug>
#include <QSqlError>
#include <QElapsedTimer>
#include "consts.h"
#include "tst_datetime.h"
#include "query.h"
#include "tableset.h"
#include "tablemodel.h"
#include "databasemodel.h"
#include "sampletable.h"
DateTimeTest::DateTimeTest(QObject *parent) : QObject(parent)
{
_baseDateTime = QDateTime::currentDateTime();
}
void DateTimeTest::initTestCase()
{
//register all entities with Qt-MetaType mechanism
REGISTER(SampleTable);
REGISTER(DB);
db.setDriver(DRIVER);
db.setHostName(HOST);
db.setDatabaseName(DATABASE);
db.setUserName(USERNAME);
db.setPassword(PASSWORD);
QTEST_ASSERT(db.open());
db.sampleTables()->query()->remove();
}
void DateTimeTest::date()
{
auto s = Nut::create<SampleTable>();
s->setD(_baseDateTime.addDays(10).date());
db.sampleTables()->append(s);
db.saveChanges();
auto q = db.sampleTables()->query()
->where(SampleTable::dField().addDays(9) < QDate::currentDate().addDays(10));
auto count = q->count();
qDebug() << q->sqlCommand();
QTEST_ASSERT(count);
}
void DateTimeTest::cleanupTestCase()
{
db.sampleTables()->query()->remove();
db.close();
}
QTEST_MAIN(DateTimeTest)

View File

@ -0,0 +1,37 @@
#ifndef MAINTEST_H
#define MAINTEST_H
#include <QtCore/QObject>
#include <QtCore/qglobal.h>
#include <QDateTime>
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
#ifdef QT_GUI_LIB
#include <QColor>
#include <QPolygonF>
#endif
#include <QUrl>
#include <QUuid>
#include "db.h"
class DateTimeTest : public QObject
{
Q_OBJECT
DB db;
QDateTime _baseDateTime;
public:
explicit DateTimeTest(QObject *parent = nullptr);
signals:
private slots:
void initTestCase();
void date();
void cleanupTestCase();
};
#endif // MAINTEST_H

View File

@ -0,0 +1,20 @@
QT += testlib sql gui
TARGET = tst_datetime
TEMPLATE = app
CONFIG += warn_on c++11
include(../common/nut-lib.pri)
SOURCES += \
db.cpp \
sampletable.cpp \
tst_datetime.cpp
HEADERS += \
db.h \
sampletable.h \
tst_datetime.h
include($$PWD/../../ci-test-init.pri)