SQLite with create and insert based on defined struct

This commit is contained in:
Filip Bucek 2019-11-12 11:25:01 +01:00
parent 995898c00c
commit d467feb7b9
14 changed files with 259 additions and 68 deletions

View File

@ -32,6 +32,7 @@ else:win32:CONFIG(debug, debug|release): LIBS += -L$$SDKDIR/debug/ -lserversdk
else:unix: LIBS += -L$$SDKDIR/ -lserversdk
QT += network sql
CONFIG += c++14
INCLUDEPATH += $$shell_quote($$PWD/src/)
DEPENDPATH += $$shell_quote($$PWD/src/serversdk)

View File

@ -72,21 +72,55 @@ void DatabaseManager::close()
mDatabase.close();
}
bool DatabaseManager::executeQuery(QSqlQuery &query)
QSqlQuery DatabaseManager::execPlainSql(const QString &sqlText)
{
if (mDryMode){
QString sqlStatement = getLastQuery(query);
qDebug() << sqlStatement;
QSqlQuery query(mDatabase);
return executeQuery(query, sqlText);
}
QSqlQuery DatabaseManager::executeQuery(QSqlQuery &query, const QString &sqlText)
{
// Get correct SQL statement and correct isSelect
// Need for output correct SQL command
// isSelect is needed for correct bahaviour of 'dryMode' only select should be executed
QString sqlStatement = sqlText;
bool isSelect = false;
if ( sqlText.isEmpty()) {
sqlStatement = getLastQuery(query);
isSelect = query.isSelect();
} else {
if (sqlText.startsWith("SELECT", Qt::CaseInsensitive)) {
isSelect = true;
}
}
if (!mDryMode || query.isSelect()){
if (!query.exec()){
QString msg = QString("Source: Database Manager, Error: %1").arg(query.lastError().text());
log(QString(msg));
emit error();
}
if (mDryMode) {
qCInfo(sdkdb) << "SQL statement: " << sqlStatement;
}
return true;
// Execute only SELECT statement or when not drymode
if ( isSelect || !mDryMode ) {
int res = false;
if ( ! sqlText.isEmpty()) { // prepared statement.
res = query.exec(sqlText);
return processResult(res, query);
} else {
res = query.exec();
return processResult(res, query);
}
}
return query;
}
QSqlQuery DatabaseManager::processResult(int res, const QSqlQuery &query) const
{
if ( !res ) {
QString msg = QString("Source: Database Manager, Error: %1").arg(query.lastError().text());
qCWarning(sdkdb) << msg;
log(msg);
}
return query;
}
QString DatabaseManager::getLastQuery(const QSqlQuery& query) const
@ -104,6 +138,24 @@ QString DatabaseManager::getLastQuery(const QSqlQuery& query) const
void DatabaseManager::log(const QString &msg) const
{
qDebug() << "database logger implement logger";
qDebug() << msg;
}
bool DatabaseManager::dryMode() const
{
return mDryMode;
}
void DatabaseManager::setDryMode(bool dryMode)
{
mDryMode = dryMode;
}
QSqlDatabase DatabaseManager::database() const
{
Q_ASSERT(mDatabase.isValid());
Q_ASSERT(mDatabase.isOpen());
return mDatabase;
}
} // core

View File

@ -21,13 +21,24 @@ public:
DatabaseManager(const QString& host, const QString& dbName, const QString& user, const QString& password, bool mDryMode = false);
~DatabaseManager();
// Attributes
bool dryMode() const;
void setDryMode(bool dryMode);
bool openSQLite(const QString &path, const QString &connectionName = QStringLiteral("qt_sql_default_connection"));
bool isValid() const;
bool isOpen() const;
void close();
// SQL handling
QSqlQuery execPlainSql(const QString &sqlText);
QSqlQuery executeQuery(QSqlQuery &query, const QString &sqlText = QString());
QSqlDatabase database() const;
private:
bool executeQuery(QSqlQuery &query);
QSqlQuery processResult(int res, const QSqlQuery &query) const;
QString getLastQuery(const QSqlQuery &query) const;
void log(const QString &msg) const;

View File

@ -12,12 +12,11 @@ DatabaseTable::DatabaseTable(QObject *parent) : QObject(parent)
/** Creates universal variant structure to hold key / value pairs */
QVariantMap DatabaseTable::toVariantMap()
QVariantMap DatabaseTable::toVariantMap() const
{
QVariantMap variantMap;
const QMetaObject *metaObj = this->metaObject();
qDebug() << "properties: ";
for (int i = metaObj->propertyOffset(); i < metaObj->propertyCount(); ++i) {
QMetaProperty prop = metaObj->property(i);
// Skip non USER so -> ( Q_PROPERTY( ...... USER false ) only
@ -35,26 +34,6 @@ QVariantMap DatabaseTable::toVariantMap()
return variantMap;
}
QString DatabaseTable::createTableSQL() const
{
QString sql = QString("CREATE TABLE %1").arg(this->metaObject()->className());
QVariantMap variantMap;
const QMetaObject *metaObj = this->metaObject();
qDebug() << "properties: ";
for (int i = metaObj->propertyOffset(); i < metaObj->propertyCount(); ++i) {
QMetaProperty prop = metaObj->property(i);
// Skip non USER so -> ( Q_PROPERTY( ...... USER false ) only
if (!prop.isUser())
continue;
QString name = prop.name();
}
}

View File

@ -27,13 +27,8 @@ class DatabaseTable : public QObject
TABLE_PROPERTY(QString, name, setName, QString());
public:
explicit DatabaseTable(QObject *parent = nullptr);
QVariantMap toVariantMap();
QString createTableSQL() const;
QVariantMap toVariantMap() const;
signals:
public slots:
};
} // namespace serversdk

View File

@ -1,8 +1,10 @@
#include "databaseutils.h"
#include "databasemanager.h"
#include "logger.h"
#include <QMetaProperty>
namespace serversdk {
/**
@ -26,21 +28,23 @@ namespace serversdk {
*
*
*/
DatabaseUtils::DatabaseUtils(const QString type)
: mSqlType(type)
DatabaseUtils::DatabaseUtils(DatabaseManager *manager, const QString type)
: mDatabaseManager(manager), mSqlType(type)
{
Q_ASSERT(mDatabaseManager);
}
QString DatabaseUtils::createTableSQL(const DatabaseTable *table, const QString tableName) const
QString DatabaseUtils::createTableText(const DatabaseTable *table, const QString table_name) const
{
QString userData;
if (tableName.isEmpty())
if (table_name.isEmpty()) {
return QString();
}
// out: "CREATE TABLE colnod_subject ( "
QString sql = QString("CREATE TABLE %1 ( ").arg(tableName);
QString sql = QString("CREATE TABLE %1 ( ").arg(table_name);
const QMetaObject *metaObj = table->metaObject();
int total = metaObj->propertyCount();
@ -97,6 +101,45 @@ QString DatabaseUtils::createTableSQL(const DatabaseTable *table, const QString
return sql;
}
QSqlQuery DatabaseUtils::createTable(const DatabaseTable *table, const QString tableName) const
{
// CREATE TABLE ...
QString sql = createTableText(table, tableName);
return mDatabaseManager->execPlainSql(sql);
}
QSqlQuery DatabaseUtils::insertIntoTable(const DatabaseTable *table, const QString table_name) const
{
QString columns;
QString values;
QVariantMap valueMap = table->toVariantMap();
auto keys = valueMap.keys();
for (auto key : keys) {
if (!columns.isEmpty()) {
columns += ", ";
values += ", ";
}
columns += key;
values += ":" + key;
}
QSqlQuery query(mDatabaseManager->database());
QString queryText = QString("INSERT OR IGNORE INTO %1 ( %2 ) VALUES ( %3 );").arg(table_name).arg(columns).arg(values);
query.prepare(queryText);
for (auto key : keys ) {
auto value = valueMap.value(key);
query.bindValue(":"+key, value);
}
QSqlQuery res = mDatabaseManager->executeQuery(query);
return res;
}
QString DatabaseUtils::sqlType() const
{
return mSqlType;
@ -107,6 +150,7 @@ void DatabaseUtils::setSqlType(const QString &sqlType)
mSqlType = sqlType;
}
QString DatabaseUtils::textSQLIteType(QVariant::Type type) const
{
switch (type) {

View File

@ -1,24 +1,38 @@
#pragma once
#include <QObject>
#include "databasetable.h"
#include <QObject>
#include <QSqlQuery>
class DatabaseUtilsTest;
namespace serversdk {
class DatabaseManager;
class DatabaseUtils : public QObject
{
Q_OBJECT
friend class ::DatabaseUtilsTest;
public:
explicit DatabaseUtils(const QString type = "SQLITE");
QString createTableSQL(const DatabaseTable *table, const QString table_name) const;
explicit DatabaseUtils(DatabaseManager *manager = nullptr, const QString type = "SQLITE");
QSqlQuery createTable(const DatabaseTable *table, const QString table_name) const;
QSqlQuery insertIntoTable(const DatabaseTable *table, const QString table_name) const;
QString sqlType() const;
void setSqlType(const QString &sqlType);
private:
QString createTableText(const DatabaseTable *table, const QString table_name) const;
QString textSQLIteType(QVariant::Type type) const;
private:
DatabaseManager *mDatabaseManager = nullptr;
QString mSqlType;
};

View File

@ -6,12 +6,15 @@
namespace serversdk {
Request::Request(QString type, QString url, QByteArray requestData)
: mType(type), mUrl(url), mRequestData(requestData)
{
}
Request::~Request()
{
}
QNetworkRequest Request::networkRequest() const
{
QNetworkRequest request(QUrl(this->mUrl));
@ -39,6 +42,16 @@ void Request::appendData(const QByteArray &array)
mResponseData += array;
}
QString Request::type() const
{
return mType;
}
void Request::setType(const QString &type)
{
mType = type;
}
QString Request::url() const
{
return mUrl;

View File

@ -2,6 +2,7 @@
#include <QString>
#include <QNetworkRequest>
#include <QDateTime>
namespace serversdk {
@ -12,7 +13,7 @@ class Request : public QObject {
public:
Request() = default;
~Request() override;
Request(QString type, QString url, QByteArray responseData = QByteArray());
Request(QString type, QString url, QByteArray requestData = QByteArray());
virtual QNetworkRequest networkRequest() const;
// Data handling data
@ -23,6 +24,8 @@ public:
// Attributes
QString url() const;
void setUrl(const QString &url);
QString type() const;
void setType(const QString &type);
// Authorization
QString userName() const;
@ -36,6 +39,10 @@ public:
QString basicAuthorization() const;
QString bearerAuthorization() const;
// Additional attributes
void logStartTime() { mStartTime = QDateTime::currentDateTime(); }
void logFinishTime() { mStartTime = QDateTime::currentDateTime(); }
private:
// Data handling
@ -46,7 +53,7 @@ signals:
void finished();
private:
QString mType; // POST, GET
QString mType = "GET"; // POST, GET
QString mUrl;
// Authorization
@ -57,6 +64,10 @@ private:
// Data
QByteArray mRequestData;
QByteArray mResponseData;
// Additional attributes
QDateTime mStartTime;
QDateTime mFinishTime;
};

View File

@ -21,14 +21,30 @@ RequestManager::RequestManager(QObject *parent)
});
}
/**
* @brief Soap::processRequest
* @param soapRequest
* @brief Process request using QNetworkAccessManger
*
* @param Request
*/
void RequestManager::processRequest(const std::shared_ptr<Request>& request)
{
QNetworkReply *reply = mNetworkAccessManager.post(request->networkRequest(), request->requestData());
QNetworkReply *reply = nullptr;
request->logStartTime();
if (request->type() == "POST") {
reply = mNetworkAccessManager.post(request->networkRequest(), request->requestData());
} else if (request->type() == "GET") {
if ( ! request->responseData().isEmpty()) {
qCWarning(sdknetwork) << "Response data is not empty, and you are trying to use get ( not sending any data)";
}
reply = mNetworkAccessManager.get(request->networkRequest());
} else if (request->type() == "PUT") {
reply = mNetworkAccessManager.put(request->networkRequest(), request->requestData());
} else {
qCritical(sdknetwork) << "Using request type:" << request->type() << "is not implemented";
return;
}
mRequestMap.insert(reply, request);
connect(reply, &QNetworkReply::sslErrors, this, &RequestManager::sslErrors);
@ -36,6 +52,7 @@ void RequestManager::processRequest(const std::shared_ptr<Request>& request)
connect(reply, &QNetworkReply::finished, this, [=]() {
std::shared_ptr<Request> request = mRequestMap.value(reply);
request->logFinishTime();
mRequestMap.remove(reply);
reply->deleteLater();
emit request->finished();

View File

@ -5,6 +5,7 @@ namespace serversdk {
SoapRequest::SoapRequest(QString action, QString endpoint, QByteArray data)
: mSoapAction(action)
{
setType("POST");
setUrl(endpoint);
setRequestData(data);
}

View File

@ -1,3 +1,4 @@
#include "serversdk/databasemanager.h"
#include "serversdk/databaseutils.h"
#include "serversdk/databasetable.h"
@ -48,8 +49,9 @@ void DatabaseUtilsTest::createTable_test()
{
auto table = std::make_unique<BookTable>();
serversdk::DatabaseUtils utils;
QString sql = utils.createTableSQL(table.get(), "subjects");
auto db = std::make_unique<serversdk::DatabaseManager>();
serversdk::DatabaseUtils utils(db.get());
QString sql = utils.createTableText(table.get(), "subjects");
QString expected = "CREATE TABLE subjects ( "
"id TEXT PRIMARY KEY, "

View File

@ -1,8 +1,17 @@
#include <QtTest>
#include "serversdk/databasemanager.h"
#include "serversdk/databaseutils.h"
// add necessary includes here
class Names : public serversdk::DatabaseTable {
Q_OBJECT
TABLE_PROPERTY(int, id, set_id, 0);
TABLE_PROPERTY(QString, name, set_name, 0);
};
class SqliteTest : public QObject
{
Q_OBJECT
@ -13,6 +22,7 @@ public:
private slots:
void createDb_test();
void createTable_test();
};
@ -52,6 +62,47 @@ void SqliteTest::createDb_test()
Q_ASSERT(!QFileInfo::exists(dbpath));
}
void SqliteTest::createTable_test()
{
// Prepare temporary path for database
QTemporaryDir dir;
QString dbpath = dir.path() + "/testdb.sqlite";
serversdk::DatabaseManager db;
db.openSQLite(dbpath);
Q_ASSERT(db.isOpen());
// Not correct way
auto names = std::make_unique<Names>();
// Creating table
serversdk::DatabaseUtils utils(&db);
QSqlQuery query = utils.createTable(names.get(), "names");
// Q_ASSERT(query.isValid());
// Inserting into table
names->set_id(2);
names->set_name("Testname");
utils.insertIntoTable(names.get(), "names");
QSqlQuery insertQuery = utils.insertIntoTable(names.get(), "names");
//Q_ASSERT(insertQuery.isValid());
// Select from table
QSqlQuery selectSQL("SELECT * FROM names");
// Q_ASSERT(db.executeQuery(selectSQL));
while (selectSQL.next()) {
QString value = selectSQL.value(1).toString();
qDebug() << "value is" << value;
}
//db.create
}
QTEST_APPLESS_MAIN(SqliteTest)
#include "tst_sqlite.moc"

View File

@ -46,15 +46,15 @@ void SoapTest::public_soap_xml()
{
QString soapAction = "blz:getBank";
QString endpoint = "http://www.thomas-bayer.com/axis2/services/BLZService";
QString xml = QString("<soapenv:Envelope " \
"xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" " \
"xmlns:blz=\"http://thomas-bayer.com/blz/\">" \
"<soapenv:Header/>" \
" <soapenv:Body>" \
" <blz:getBank>" \
" <blz:blz>%1</blz:blz>" \
" </blz:getBank>" \
"</soapenv:Body>" \
QString xml = QString("<soapenv:Envelope "
"xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" "
"xmlns:blz=\"http://thomas-bayer.com/blz/\">"
"<soapenv:Header/>"
" <soapenv:Body>"
" <blz:getBank>"
" <blz:blz>%1</blz:blz>"
" </blz:getBank>"
"</soapenv:Body>"
"</soapenv:Envelope>").arg("10020200");
QByteArray xmlRequest = xml.toUtf8();