diff --git a/src/nut/generators/mysqlgenerator.cpp b/src/nut/generators/mysqlgenerator.cpp index 9e5f648..5b1329e 100644 --- a/src/nut/generators/mysqlgenerator.cpp +++ b/src/nut/generators/mysqlgenerator.cpp @@ -131,13 +131,13 @@ QString MySqlGenerator::escapeValue(const QVariant &v) const return v.toBool() ? QStringLiteral("1") : QStringLiteral("0"); if (v.type() == QVariant::Time) - return v.toTime().toString(QStringLiteral("'HH:mm:ss'")); + return v.toTime().toString(QStringLiteral("''HH:mm:ss''")); if (v.type() == QVariant::Date) - return v.toDate().toString(QStringLiteral("'yyyy-MM-dd'")); + return v.toDate().toString(QStringLiteral("''yyyy-MM-dd''")); if (v.type() == QVariant::DateTime) - return v.toDateTime().toString(QStringLiteral("'yyyy-MM-dd HH:mm:ss'")); + return v.toDateTime().toString(QStringLiteral("''yyyy-MM-dd HH:mm:ss''")); //#ifdef QT_GUI_LIB // if (v.type() == QVariant::Polygon) { diff --git a/src/nut/generators/postgresqlgenerator.cpp b/src/nut/generators/postgresqlgenerator.cpp index cd52026..489394c 100644 --- a/src/nut/generators/postgresqlgenerator.cpp +++ b/src/nut/generators/postgresqlgenerator.cpp @@ -213,13 +213,13 @@ QString PostgreSqlGenerator::diff(FieldModel *oldField, FieldModel *newField) QString PostgreSqlGenerator::escapeValue(const QVariant &v) const { if (v.type() == QVariant::Time) - return v.toTime().toString(QStringLiteral("'HH:mm:ss'")); + return v.toTime().toString(QStringLiteral("''HH:mm:ss''")); if (v.type() == QVariant::Date) - return v.toDate().toString(QStringLiteral("'yyyy-MM-dd'")); + return v.toDate().toString(QStringLiteral("''yyyy-MM-dd''")); if (v.type() == QVariant::DateTime) - return v.toDateTime().toString(QStringLiteral("'yyyy-MM-dd HH:mm:ss'")); + return v.toDateTime().toString(QStringLiteral("''yyyy-MM-dd HH:mm:ss''")); if (v.type() == QVariant::StringList) return QStringLiteral("'{") diff --git a/src/nut/generators/sqlitegenerator.cpp b/src/nut/generators/sqlitegenerator.cpp index 2087989..656f854 100644 --- a/src/nut/generators/sqlitegenerator.cpp +++ b/src/nut/generators/sqlitegenerator.cpp @@ -302,13 +302,13 @@ QString SqliteGenerator::createConditionalPhrase(const PhraseData *d) const QString SqliteGenerator::escapeValue(const QVariant &v) const { if (v.type() == QVariant::Time) - return v.toTime().toString(QStringLiteral("'HH:mm:ss'")); + return v.toTime().toString(QStringLiteral("''HH:mm:ss''")); if (v.type() == QVariant::Date) - return v.toDate().toString(QStringLiteral("'yyyy-MM-dd'")); + return v.toDate().toString(QStringLiteral("''yyyy-MM-dd''")); if (v.type() == QVariant::DateTime) - return v.toDateTime().toString(QStringLiteral("'yyyy-MM-dd HH:mm:ss'")); + return v.toDateTime().toString(QStringLiteral("''yyyy-MM-dd HH:mm:ss''")); return SqlGeneratorBase::escapeValue(v); } diff --git a/src/nut/generators/sqlservergenerator.cpp b/src/nut/generators/sqlservergenerator.cpp index 77b0bd2..8f86ae5 100644 --- a/src/nut/generators/sqlservergenerator.cpp +++ b/src/nut/generators/sqlservergenerator.cpp @@ -184,13 +184,13 @@ QString SqlServerGenerator::escapeValue(const QVariant &v) const // } case QVariant::Time: - return v.toTime().toString(QStringLiteral("'HH:mm:ss'")); + return v.toTime().toString(QStringLiteral("''HH:mm:ss''")); case QVariant::Date: - return v.toDate().toString(QStringLiteral("'yyyy-MM-dd'")); + return v.toDate().toString(QStringLiteral("''yyyy-MM-dd''")); case QVariant::DateTime: - return v.toDateTime().toString(QStringLiteral("'yyyy-MM-dd HH:mm:ss'")); + return v.toDateTime().toString(QStringLiteral("''yyyy-MM-dd HH:mm:ss''")); default: return SqlGeneratorBase::escapeValue(v); diff --git a/src/nut/query.h b/src/nut/query.h index 6797f15..916b845 100644 --- a/src/nut/query.h +++ b/src/nut/query.h @@ -389,7 +389,7 @@ Q_OUTOFLINE_TEMPLATE int Query::count() Q_D(Query); d->joins.prepend(d->tableName); - d->select = "COUNT(*)"; + d->select = QStringLiteral("COUNT(*)"); d->sql = d->database->sqlGenerator()->selectCommand( d->tableName, SqlGeneratorBase::Count, diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro index 1d0d3e8..18f5606 100644 --- a/tests/auto/auto.pro +++ b/tests/auto/auto.pro @@ -9,8 +9,9 @@ SUBDIRS += \ tst_generators \ tst_upgrades \ tst_json \ - tst_datetime + tst_datetime \ + tst_sametype cmake.CONFIG += no_run-tests_target prepareRecursiveTarget(run-tests) -QMAKE_EXTRA_TARGETS += run-tests \ No newline at end of file +QMAKE_EXTRA_TARGETS += run-tests diff --git a/tests/auto/common/mysql/consts.h b/tests/auto/common/mysql/consts.h new file mode 100644 index 0000000..62ff2df --- /dev/null +++ b/tests/auto/common/mysql/consts.h @@ -0,0 +1,10 @@ +#ifndef DATABASE_CONSTS_H +#define DATABASE_CONSTS_H + +#define DRIVER QStringLiteral("QMYSQL") +#define DATABASE QStringLiteral("nut_test_%1_db").arg(metaObject()->className()).toLower()) +#define HOST QString() +#define USERNAME QString() +#define PASSWORD QString() + +#endif // DATABASE_CONSTS_H diff --git a/tests/auto/common/nut-lib.pri b/tests/auto/common/nut-lib.pri index d6dacb4..c3f5c99 100644 --- a/tests/auto/common/nut-lib.pri +++ b/tests/auto/common/nut-lib.pri @@ -1,7 +1,60 @@ +contains(debug_and_release, CONFIG): message(debug_and_release) + +debug_and_release:!ReleaseBuild:!DebugBuild { + runtarget.target = run-tests + runtarget.CONFIG = recursive + runtarget.recurse_target = run-tests + QMAKE_EXTRA_TARGETS += runtarget +} else { + oneshell.target = .ONESHELL + QMAKE_EXTRA_TARGETS += oneshell + + win32:!win32-g++ { + CONFIG(debug, debug|release): outdir_helper = debug + CONFIG(release, debug|release): outdir_helper = release + runtarget.target = run-tests + !compat_test: runtarget.depends += $(DESTDIR_TARGET) + runtarget.commands += set PATH=$$shell_path($$shadowed($$dirname(_QMAKE_CONF_))/bin);$$shell_path($$[QT_INSTALL_BINS]);$(PATH) + runtarget.commands += $$escape_expand(\\n\\t)set QT_PLUGIN_PATH=$$shadowed($$dirname(_QMAKE_CONF_))/plugins;$$[QT_INSTALL_PLUGINS];$(QT_PLUGIN_PATH) + runtarget.commands += $$escape_expand(\\n\\t)set QML2_IMPORT_PATH=$$shadowed($$dirname(_QMAKE_CONF_))/qml;$$[QT_INSTALL_QML];$(QML2_IMPORT_PATH) + !isEmpty(LOGGING_RULES): runtarget.commands += $$escape_expand(\\n\\t)set \"QT_LOGGING_RULES=$$LOGGING_RULES\" + runtarget.commands += $$escape_expand(\\n\\t)if exist $${outdir_helper}\\fail del $${outdir_helper}\\fail + runtarget.commands += $$escape_expand(\\n\\t)start /w call $(DESTDIR_TARGET) ^> $${outdir_helper}\\test.log ^|^| echo FAIL ^> $${outdir_helper}\\fail ^& exit 0 + runtarget.commands += $$escape_expand(\\n\\t)type $${outdir_helper}\\test.log + runtarget.commands += $$escape_expand(\\n\\t)if exist $${outdir_helper}\\fail exit 42 + QMAKE_EXTRA_TARGETS += runtarget + } else { + win32-g++: QMAKE_DIRLIST_SEP = ";" + runtarget.commands += export PATH=\"$$shell_path($$shadowed($$dirname(_QMAKE_CONF_))/bin):$$shell_path($$[QT_INSTALL_BINS]):$${LITERAL_DOLLAR}$${LITERAL_DOLLAR}PATH\" + runtarget.commands += $$escape_expand(\\n\\t)export QT_PLUGIN_PATH=\"$$shadowed($$dirname(_QMAKE_CONF_))/plugins$${QMAKE_DIRLIST_SEP}$$[QT_INSTALL_PLUGINS]$${QMAKE_DIRLIST_SEP}$(QT_PLUGIN_PATH)\" + runtarget.commands += $$escape_expand(\\n\\t)export QML2_IMPORT_PATH=\"$$shadowed($$dirname(_QMAKE_CONF_))/qml$${QMAKE_DIRLIST_SEP}$$[QT_INSTALL_QML]$${QMAKE_DIRLIST_SEP}$(QML2_IMPORT_PATH)\" + !isEmpty(LOGGING_RULES): runtarget.commands += $$escape_expand(\\n\\t)export QT_LOGGING_RULES=\"$$LOGGING_RULES\" + win32-g++: QMAKE_DIRLIST_SEP = ":" + + linux|win32-g++ { + runtarget.commands += $$escape_expand(\\n\\t)export LD_LIBRARY_PATH=\"$$shadowed($$dirname(_QMAKE_CONF_))/lib$${QMAKE_DIRLIST_SEP}$$[QT_INSTALL_LIBS]$${QMAKE_DIRLIST_SEP}$(LD_LIBRARY_PATH)\" + runtarget.commands += $$escape_expand(\\n\\t)export QT_QPA_PLATFORM=minimal + } else:mac { + runtarget.commands += $$escape_expand(\\n\\t)export DYLD_LIBRARY_PATH=\"$$shadowed($$dirname(_QMAKE_CONF_))/lib:$$[QT_INSTALL_LIBS]:$(DYLD_LIBRARY_PATH)\" + runtarget.commands += $$escape_expand(\\n\\t)export DYLD_FRAMEWORK_PATH=\"$$shadowed($$dirname(_QMAKE_CONF_))/lib:$$[QT_INSTALL_LIBS]:$(DYLD_FRAMEWORK_PATH)\" + } + + runtarget.target = run-tests + win32-g++ { + !compat_test: runtarget.depends += $(DESTDIR_TARGET) + runtarget.commands += $$escape_expand(\\n\\t)./$(DESTDIR_TARGET) + } else { + !compat_test: runtarget.depends += $(TARGET) + runtarget.commands += $$escape_expand(\\n\\t)./$(TARGET) + } + QMAKE_EXTRA_TARGETS += runtarget + } +} + win32 { CONFIG(debug,debug|release): LIBDIR = $$absolute_path($$OUT_PWD/../../../src/nut/debug) CONFIG(release,debug|release): LIBDIR = $$absolute_path($$OUT_PWD/../../../src/nut/release) - LIBS += -L$$LIBDIR -lnut +# LIBS += -L$$LIBDIR -lnut } else { LIBDIR = $$absolute_path($$OUT_PWD/../../../lib) android: { @@ -19,7 +72,7 @@ win32 { LIBS += -L$$LIBDIR -lnut_x86_64 } } else { -# LIBS += -L$$LIBDIR -lnut +# LIBS += -L$$LIBDIR } } @@ -27,6 +80,7 @@ win32 { INCLUDEPATH += $$PWD/../common QT += nut +CONFIG += testcase DEFINES += NUT_SHARED_POINTER DEFINES += NUT_PATH=\\\"$$PWD/../../\\\" diff --git a/tests/auto/common/pgsql/consts.h b/tests/auto/common/pgsql/consts.h new file mode 100644 index 0000000..7066d6e --- /dev/null +++ b/tests/auto/common/pgsql/consts.h @@ -0,0 +1,10 @@ +#ifndef DATABASE_CONSTS_H +#define DATABASE_CONSTS_H + +#define DRIVER QStringLiteral("QPSQL") +#define DATABASE QStringLiteral("nut_test_%1_db").arg(metaObject()->className()).toLower()) +#define HOST QString() +#define USERNAME QStringLiteral("postgres") +#define PASSWORD QStringLiteral("root") + +#endif // DATABASE_CONSTS_H diff --git a/tests/auto/common/sqlite/consts.h b/tests/auto/common/sqlite/consts.h new file mode 100644 index 0000000..a6bcaef --- /dev/null +++ b/tests/auto/common/sqlite/consts.h @@ -0,0 +1,10 @@ +#ifndef DATABASE_CONSTS_H +#define DATABASE_CONSTS_H + +#define DRIVER QStringLiteral("QSQLITE") +#define DATABASE QStringLiteral("nut_test_%1_db").arg(metaObject()->className()).toLower()) +#define HOST QString() +#define USERNAME QString() +#define PASSWORD QString() + +#endif // DATABASE_CONSTS_H diff --git a/tests/auto/common/sqlserver/consts.h b/tests/auto/common/sqlserver/consts.h new file mode 100644 index 0000000..a78782d --- /dev/null +++ b/tests/auto/common/sqlserver/consts.h @@ -0,0 +1,11 @@ +#ifndef DATABASE_CONSTS_H +#define DATABASE_CONSTS_H + +#define DRIVER "QODBC" +#define DATABASE QString("DRIVER={SQL Server};Server=.;Database=%1;Uid=sa;Port=1433;Pwd=qwe123!@#;WSID=.") \ + .arg(QString("nut_test_%1_db").arg(metaObject()->className()).toLower()) +#define HOST QStringLiteral(".") +#define USERNAME QString() +#define PASSWORD QString() + +#endif // DATABASE_CONSTS_H diff --git a/tests/auto/tst_basic/tst_basic.cpp b/tests/auto/tst_basic/tst_basic.cpp index 0bd73de..555d8fe 100644 --- a/tests/auto/tst_basic/tst_basic.cpp +++ b/tests/auto/tst_basic/tst_basic.cpp @@ -170,10 +170,15 @@ void BasicTest::selectPosts() void BasicTest::selectScoreAverage() { - auto avg = db.scores()->query() - ->join() - ->setWhere(Post::idField() == 1) - ->average(Score::scoreField()); + bool ok; + auto avg = db.scores() + ->query() + ->join() + ->where(Post::idField() == postId) + ->average(Score::scoreField()) + .toInt(&ok); + + QTEST_ASSERT(ok); QCOMPARE(avg, 2); } @@ -210,7 +215,7 @@ void BasicTest::selectPostIds() { auto q = db.posts()->query(); auto ids = q->select(Post::idField()); -qDebug() << ids.count(); + QTEST_ASSERT(ids.count() == 2); } diff --git a/tests/auto/tst_sametype/.gitignore b/tests/auto/tst_sametype/.gitignore new file mode 100644 index 0000000..fab7372 --- /dev/null +++ b/tests/auto/tst_sametype/.gitignore @@ -0,0 +1,73 @@ +# This file is used to ignore files which are generated +# ---------------------------------------------------------------------------- + +*~ +*.autosave +*.a +*.core +*.moc +*.o +*.obj +*.orig +*.rej +*.so +*.so.* +*_pch.h.cpp +*_resource.rc +*.qm +.#* +*.*# +core +!core/ +tags +.DS_Store +.directory +*.debug +Makefile* +*.prl +*.app +moc_*.cpp +ui_*.h +qrc_*.cpp +Thumbs.db +*.res +*.rc +/.qmake.cache +/.qmake.stash + +# qtcreator generated files +*.pro.user* + +# xemacs temporary files +*.flc + +# Vim temporary files +.*.swp + +# Visual Studio generated files +*.ib_pdb_index +*.idb +*.ilk +*.pdb +*.sln +*.suo +*.vcproj +*vcproj.*.*.user +*.ncb +*.sdf +*.opensdf +*.vcxproj +*vcxproj.* + +# MinGW generated files +*.Debug +*.Release + +# Python byte code +*.pyc + +# Binaries +# -------- +*.dll +*.exe + diff --git a/tests/auto/tst_sametype/db.cpp b/tests/auto/tst_sametype/db.cpp new file mode 100644 index 0000000..fcd8a80 --- /dev/null +++ b/tests/auto/tst_sametype/db.cpp @@ -0,0 +1,10 @@ +#include "db.h" +#include "sampletable.h" + +DB::DB() : Nut::Database() + , m_users1(new Nut::TableSet(this)) + , m_users2(new Nut::TableSet(this)) + , m_users3(new Nut::TableSet(this)) +{ + +} diff --git a/tests/auto/tst_sametype/db.h b/tests/auto/tst_sametype/db.h new file mode 100644 index 0000000..886e1a1 --- /dev/null +++ b/tests/auto/tst_sametype/db.h @@ -0,0 +1,23 @@ +#ifndef DB1_H +#define DB1_H + +#include "database.h" + +class SampleTable; +class DB : public Nut::Database +{ + Q_OBJECT + + NUT_DB_VERSION(1) + + NUT_DECLARE_TABLE(SampleTable, users1) + NUT_DECLARE_TABLE(SampleTable, users2) + NUT_DECLARE_TABLE(SampleTable, users3) + +public: + DB(); +}; + +Q_DECLARE_METATYPE(DB*) + +#endif // DB1_H diff --git a/tests/auto/tst_sametype/sampletable.cpp b/tests/auto/tst_sametype/sampletable.cpp new file mode 100644 index 0000000..120c146 --- /dev/null +++ b/tests/auto/tst_sametype/sampletable.cpp @@ -0,0 +1,7 @@ +#include "sampletable.h" + + +SampleTable::SampleTable(QObject *parent) : Nut::Table (parent) +{ + +} diff --git a/tests/auto/tst_sametype/sampletable.h b/tests/auto/tst_sametype/sampletable.h new file mode 100644 index 0000000..4931985 --- /dev/null +++ b/tests/auto/tst_sametype/sampletable.h @@ -0,0 +1,23 @@ +#ifndef TABLE1_H +#define TABLE1_H + +#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(QString, name, name, setName) + NUT_DECLARE_FIELD(QString, password, password, setPassword) + +public: + Q_INVOKABLE SampleTable(QObject *parent = Q_NULLPTR); + +}; + +Q_DECLARE_METATYPE(SampleTable*) + +#endif // TABLE1_H diff --git a/tests/auto/tst_sametype/tst_sametype.pro b/tests/auto/tst_sametype/tst_sametype.pro new file mode 100644 index 0000000..736a7d0 --- /dev/null +++ b/tests/auto/tst_sametype/tst_sametype.pro @@ -0,0 +1,18 @@ +QT += testlib sql + +TARGET = tst_upgrades +TEMPLATE = app +CONFIG += warn_on c++11 + +include(../common/nut-lib.pri) + +SOURCES += \ + db.cpp \ + sampletable.cpp \ + tst_sametypes.cpp + +HEADERS += \ + db.h \ + sampletable.h \ + tst_sametypes.h + diff --git a/tests/auto/tst_sametype/tst_sametypes.cpp b/tests/auto/tst_sametype/tst_sametypes.cpp new file mode 100644 index 0000000..3f5a96e --- /dev/null +++ b/tests/auto/tst_sametype/tst_sametypes.cpp @@ -0,0 +1,148 @@ +#include + +#include "db.h" +#include "sampletable.h" +#include "query.h" + +#include "tst_sametypes.h" +#include "consts.h" + +SameTypes::SameTypes() +{ + +} + +SameTypes::~SameTypes() +{ + +} + + +void SameTypes::initTestCase() +{ + REGISTER(DB); + REGISTER(SampleTable); + + db.setDriver(DRIVER); + db.setHostName(HOST); + db.setDatabaseName(DATABASE); + db.setUserName(USERNAME); + db.setPassword(PASSWORD); + + db.open(); +} + +void SameTypes::insert() +{ + insertOnList(1, "1"); + insertOnList(2, "2"); + insertOnList(3, "3"); +} + +void SameTypes::counts() +{ + for (int i = 1; i < 4; ++i) { + auto t = query(i); + + QTEST_ASSERT(t != nullptr); + QCOMPARE(t->toList().count(), 1); + } +} + +void SameTypes::read() +{ + QCOMPARE(readPassword(1), "1"); + QCOMPARE(readPassword(2), "2"); + QCOMPARE(readPassword(3), "3"); +} + +void SameTypes::insertOnList(char no, const QString &password) +{ + Nut::TableSet *tableSet; + + switch (no) { + case 1: + tableSet = db.users1(); + break; + + case 2: + tableSet = db.users2(); + break; + + case 3: + tableSet = db.users3(); + break; + + default: + return; + } + + bool ok; + auto q = tableSet->query(); + int n = q->insert((SampleTable::nameField() = "user") + & (SampleTable::passwordField() = password)) + .toInt(&ok); + + qDebug() << q->sqlCommand(); + QTEST_ASSERT(ok); + + QTEST_ASSERT(n != 0); +} + +QString SameTypes::readPassword(char no) +{ + Nut::TableSet *tableSet; + + switch (no) { + case 1: + tableSet = db.users1(); + break; + + case 2: + tableSet = db.users2(); + break; + + case 3: + tableSet = db.users3(); + break; + + default: + return QString(); + } + + bool ok; + auto q = tableSet->query(); + QStringList passwordList = q->where(SampleTable::nameField() == "user") + ->select(SampleTable::passwordField()); + + + qDebug() << q->sqlCommand(); + QTEST_ASSERT(passwordList.size() == 1); + + return passwordList.first(); +} + +Nut::Query *SameTypes::query(int n) +{ + switch (n) { + case 1: + return db.users1()->query(); + break; + + case 2: + return db.users2()->query(); + break; + + case 3: + return db.users3()->query(); + break; + + default: + return nullptr; + } +} + + + +QTEST_APPLESS_MAIN(SameTypes) + diff --git a/tests/auto/tst_sametype/tst_sametypes.h b/tests/auto/tst_sametype/tst_sametypes.h new file mode 100644 index 0000000..7c5b5ce --- /dev/null +++ b/tests/auto/tst_sametype/tst_sametypes.h @@ -0,0 +1,36 @@ +#ifndef TST_UPGRADES_H +#define TST_UPGRADES_H + +#include +#include "db.h" + + +namespace Nut { +class Database; +template +class Query; +} +class SameTypes : public QObject +{ + Q_OBJECT + + DB db; + + void insertOnList(char no, const QString &password); + QString readPassword(char no); + Nut::Query *query(int n); + +public: + SameTypes(); + ~SameTypes(); + +private slots: + void initTestCase(); + + void insert(); + void counts(); + void read(); + +}; + +#endif // TST_UPGRADES_H