Merge branch 'possible-change' into 'master'

WIP: add function for UPDATE, needs to be edited

See merge request spaceti-app/integrations/common/server-sdk!6
This commit is contained in:
Ondřej Fischer 2019-11-19 09:22:24 +00:00
commit 2d305163a8
9 changed files with 186 additions and 21 deletions

View File

@ -116,6 +116,12 @@ QSqlQuery DatabaseManager::executeQuery(QSqlQuery &query, const QString &sqlText
return query; return query;
} }
QSqlQuery DatabaseManager::createQuery()
{
QSqlQuery query(mDatabase);
return query;
}
QSqlQuery DatabaseManager::processResult(int res, const QSqlQuery &query) const QSqlQuery DatabaseManager::processResult(int res, const QSqlQuery &query) const
{ {
if ( !res ) { if ( !res ) {

View File

@ -25,7 +25,6 @@ public:
bool dryMode() const; bool dryMode() const;
void setDryMode(bool dryMode); void setDryMode(bool dryMode);
bool openSQLite(const QString &path, const QString &connectionName = QStringLiteral("qt_sql_default_connection")); bool openSQLite(const QString &path, const QString &connectionName = QStringLiteral("qt_sql_default_connection"));
bool openPostgres(const QString& host, const QString& dbName, const QString& user, const QString& password, const QString &connectionName = QStringLiteral("qt_sql_default_connection")); bool openPostgres(const QString& host, const QString& dbName, const QString& user, const QString& password, const QString &connectionName = QStringLiteral("qt_sql_default_connection"));
bool isValid() const; bool isValid() const;
@ -35,6 +34,7 @@ public:
// SQL handling // SQL handling
QSqlQuery execPlainSql(const QString &sqlText); QSqlQuery execPlainSql(const QString &sqlText);
QSqlQuery executeQuery(QSqlQuery &query, const QString &sqlText = QString()); QSqlQuery executeQuery(QSqlQuery &query, const QString &sqlText = QString());
QSqlQuery createQuery();
QSqlDatabase database() const; QSqlDatabase database() const;

View File

@ -19,6 +19,16 @@ QByteArray DatabaseTable::jsonData() const
return doc.toJson(QJsonDocument::Compact); return doc.toJson(QJsonDocument::Compact);
} }
bool DatabaseTable::fromJson(const QByteArray &data)
{
// in: JSON ( e.g. {"id": 300} )
QJsonDocument doc = QJsonDocument::fromJson(data);
QVariantMap variant = qvariant_cast<QVariantMap>(doc.toVariant());
// Populate this object data
bool res = fromVariantMap(variant);
return res;
}
/** Creates universal variant structure to hold key / value pairs */ /** Creates universal variant structure to hold key / value pairs */
QVariantMap DatabaseTable::toVariantMap() const QVariantMap DatabaseTable::toVariantMap() const
@ -76,16 +86,6 @@ QList<std::shared_ptr<DatabaseTable> > DatabaseTable::fromListVariantMap(const Q
return list; return list;
} }
bool DatabaseTable::fromJson(const QByteArray &data)
{
// in: JSON ( e.g. {"id": 300} )
QJsonDocument doc = QJsonDocument::fromJson(data);
QVariantMap variant = qvariant_cast<QVariantMap>(doc.toVariant());
// Populate this object data
bool res = fromVariantMap(variant);
return res;
}
QString DatabaseTable::textSQLIteType(QVariant::Type type) const QString DatabaseTable::textSQLIteType(QVariant::Type type) const
{ {

View File

@ -84,13 +84,13 @@ public:
* @brief Creates JSON from QMetaObject data ( Q_PROPERTY ) -> TABLE_PROPERTY * @brief Creates JSON from QMetaObject data ( Q_PROPERTY ) -> TABLE_PROPERTY
* @return text json e.g. { "id": 00344 } * @return text json e.g. { "id": 00344 }
*/ */
QByteArray jsonData() const; virtual QByteArray jsonData() const;
/** /**
* @brief Populates object with JSON {"id": 300} ) * @brief Populates object with JSON {"id": 300} )
* @return true if success TODO: not implemented corrrectly * @return true if success TODO: not implemented corrrectly
*/ */
bool fromJson(const QByteArray &data); virtual bool fromJson(const QByteArray &data);
/** /**
* @brief Creates VariantMap from QMetaObject data ( Q_PROPERTY ) * @brief Creates VariantMap from QMetaObject data ( Q_PROPERTY )

View File

@ -56,7 +56,7 @@ QString DatabaseUtils::createTableText(const DatabaseTable *table, const QString
if (!prop.isUser()) if (!prop.isUser())
continue; continue;
QString name = prop.name(); QString name = fromCamelCase(prop.name());
QVariant::Type type = prop.type(); QVariant::Type type = prop.type();
QString textType; QString textType;
@ -116,9 +116,12 @@ QSqlQuery DatabaseUtils::insertIntoTable(const DatabaseTable *table, const QStri
QVariantMap valueMap = table->toVariantMap(); QVariantMap valueMap = table->toVariantMap();
// in: id / 23233
// out: columns: id
// out: values: :id
auto keys = valueMap.keys(); auto keys = valueMap.keys();
for (auto key : keys) { for (auto _key : keys) {
QString key = fromCamelCase(_key);
if (!columns.isEmpty()) { if (!columns.isEmpty()) {
columns += ", "; columns += ", ";
values += ", "; values += ", ";
@ -131,8 +134,42 @@ QSqlQuery DatabaseUtils::insertIntoTable(const DatabaseTable *table, const QStri
QString queryText = QString("INSERT INTO %1 ( %2 ) VALUES ( %3 );").arg(table_name).arg(columns).arg(values); QString queryText = QString("INSERT INTO %1 ( %2 ) VALUES ( %3 );").arg(table_name).arg(columns).arg(values);
query.prepare(queryText); query.prepare(queryText);
for (auto key : keys ) { for (auto _key : keys ) {
auto value = valueMap.value(key); QString key = fromCamelCase(_key);
auto value = valueMap.value(_key);
query.bindValue(":"+key, value);
}
QSqlQuery res = mDatabaseManager->executeQuery(query);
return res;
}
QSqlQuery DatabaseUtils::updateTable(const DatabaseTable *table, const QString table_name) const
{
QString columnsAndValues;
// tepmporary, for edit ( add one more parameter to func sth like QList with conditions
QString conditions;
conditions = "id = :id";
QVariantMap valueMap = table->toVariantMap();
auto keys = valueMap.keys();
for (auto _key : keys) {
QString key = fromCamelCase(_key);
if (!columnsAndValues.isEmpty()) {
columnsAndValues += ", ";
}
columnsAndValues += key + " = :" + key;
}
QSqlQuery query(mDatabaseManager->database());
QString queryText = QString("UPDATE %1 SET %2 WHERE %3;").arg(table_name).arg(columnsAndValues).arg(conditions);
query.prepare(queryText);
for (auto _key : keys ) {
QString key = fromCamelCase(_key);
auto value = valueMap.value(_key);
query.bindValue(":"+key, value); query.bindValue(":"+key, value);
} }
@ -152,6 +189,27 @@ void DatabaseUtils::setSqlType(const QString &sqlType)
mSqlType = sqlType; mSqlType = sqlType;
} }
QString DatabaseUtils::fromCamelCase(const QString &s)
{
static QRegularExpression regExp1 {"(.)([A-Z][a-z]+)"};
static QRegularExpression regExp2 {"([a-z0-9])([A-Z])"};
QString result = s;
result.replace(regExp1, "\\1_\\2");
result.replace(regExp2, "\\1_\\2");
return result.toLower();
}
QString serversdk::DatabaseUtils::toCamelCase(const QString &s)
{
QStringList parts = s.split('_', QString::SkipEmptyParts);
for (int i=1; i<parts.size(); ++i)
parts[i].replace(0, 1, parts[i][0].toUpper());
return parts.join("");
}
} // namespace serversdk } // namespace serversdk

View File

@ -3,6 +3,7 @@
#include "databasetable.h" #include "databasetable.h"
#include <QObject> #include <QObject>
#include <QRegularExpression>
#include <QSqlQuery> #include <QSqlQuery>
#include <QSqlRecord> #include <QSqlRecord>
@ -24,6 +25,8 @@ public:
QSqlQuery insertIntoTable(const DatabaseTable *table, const QString table_name) const; QSqlQuery insertIntoTable(const DatabaseTable *table, const QString table_name) const;
QSqlQuery updateTable(const DatabaseTable *table, const QString table_name) const;
template <class T> template <class T>
QList<std::shared_ptr<T>> tableFromQuery(QSqlQuery query) const { QList<std::shared_ptr<T>> tableFromQuery(QSqlQuery query) const {
QList<std::shared_ptr<T>> list; QList<std::shared_ptr<T>> list;
@ -46,6 +49,9 @@ public:
QString sqlType() const; QString sqlType() const;
void setSqlType(const QString &sqlType); void setSqlType(const QString &sqlType);
static QString fromCamelCase(const QString &s);
static QString toCamelCase(const QString& s);
private: private:
QString createTableText(const DatabaseTable *table, const QString table_name) const; QString createTableText(const DatabaseTable *table, const QString table_name) const;
@ -54,5 +60,6 @@ private:
QString mSqlType; QString mSqlType;
}; };
} // namespace serversdk } // namespace serversdk

View File

@ -13,6 +13,58 @@ class BookTable : public serversdk::DatabaseTable
}; };
QString enumjson = R"({"authErrors":255,"flags":["Enabled","NoValidity"],"subjectId":"1438aade-3aa6-4885-8e0f-138dedae727a"})";
class EnumTest : public serversdk::DatabaseTable
{
Q_OBJECT
TABLE_PROPERTY(int, authErrors, setAuthErrors, 0);
TABLE_PROPERTY(bool, enabled, setEnabled, false);
TABLE_PROPERTY(bool, noValidity, setNoValidity, false);
TABLE_PROPERTY(QString, subjectId, setSubjectId, QString());
public:
QByteArray jsonData() const override
{
auto variantMap = this->toVariantMap();
auto enabled = variantMap["enabled"].toBool();
auto noValidity = variantMap["noValidity"].toBool();
variantMap.remove("enabled");
variantMap.remove("noValidity");
QVariantList flags;
if ( enabled ) {
flags << "Enabled";
}
if ( noValidity ) {
flags << "NoValidity";
}
variantMap.insert("flags", flags);
QJsonDocument doc = QJsonDocument::fromVariant(variantMap);
return doc.toJson(QJsonDocument::Compact);
}
bool fromJson(const QByteArray &data) override
{
QJsonDocument doc = QJsonDocument::fromJson(data);
QVariantMap variant = qvariant_cast<QVariantMap>(doc.toVariant());
QVariantList flags = variant["flags"].toList();
for (auto value : flags) {
if ( value.toString() == "Enabled") {
variant.insert("enabled", true);
}
if ( value.toString() == "NoValidity") {
variant.insert("noValidity", true);
}
}
variant.remove("flags");
// Populate this object data
bool res = fromVariantMap(variant);
return res;
}
};
class DatabaseTableTest : public QObject class DatabaseTableTest : public QObject
{ {
@ -26,6 +78,7 @@ private slots:
void constructor_test(); void constructor_test();
void qvariant_test(); void qvariant_test();
void json_test(); void json_test();
void enum_test();
}; };
@ -61,6 +114,35 @@ void DatabaseTableTest::json_test()
QCOMPARE(table->jsonData(), expected); QCOMPARE(table->jsonData(), expected);
} }
void DatabaseTableTest::enum_test()
{
auto table = std::make_unique<EnumTest>();
table->setAuthErrors(255);
table->setNoValidity(true);
table->setEnabled(true);
table->setSubjectId("1438aade-3aa6-4885-8e0f-138dedae727a");
QCOMPARE(table->jsonData(), enumjson.toUtf8());
EnumTest jsonTest;
jsonTest.fromJson(enumjson.toUtf8());
QCOMPARE(jsonTest.authErrors(), 255);
QCOMPARE(jsonTest.noValidity(), true);
QCOMPARE(jsonTest.enabled(), true);
QCOMPARE(jsonTest.subjectId(), QStringLiteral("1438aade-3aa6-4885-8e0f-138dedae727a"));
}
QTEST_APPLESS_MAIN(DatabaseTableTest) QTEST_APPLESS_MAIN(DatabaseTableTest)
#include "tst_databasetable.moc" #include "tst_databasetable.moc"

View File

@ -33,6 +33,8 @@ public:
private slots: private slots:
void createTable_test(); void createTable_test();
void toCamelCase_test();
void fromCamelCase_test();
}; };
@ -64,6 +66,18 @@ void DatabaseUtilsTest::createTable_test()
QCOMPARE(sql, expected); QCOMPARE(sql, expected);
} }
void DatabaseUtilsTest::toCamelCase_test()
{
QString test1 = "id_name";
QCOMPARE(serversdk::DatabaseUtils::toCamelCase(test1), QStringLiteral("idName"));
}
void DatabaseUtilsTest::fromCamelCase_test()
{
QString test1 = "idName";
QCOMPARE(serversdk::DatabaseUtils::fromCamelCase(test1), QStringLiteral("id_name"));
}
QTEST_APPLESS_MAIN(DatabaseUtilsTest) QTEST_APPLESS_MAIN(DatabaseUtilsTest)

View File

@ -90,9 +90,7 @@ void SqliteTest::createTable_test()
// ENSURE SAME // ENSURE SAME
QCOMPARE(list.count(), 1); QCOMPARE(list.count(), 1);
auto first = list.first(); auto names_tab = list.first();
QVERIFY(first);
auto names_tab = std::dynamic_pointer_cast<Names>(first);
QVERIFY(names_tab); QVERIFY(names_tab);
QCOMPARE(names_tab->name(), QStringLiteral("Testname")); QCOMPARE(names_tab->name(), QStringLiteral("Testname"));