Skip to content

Commit

Permalink
SHV API: Add SQL node
Browse files Browse the repository at this point in the history
  • Loading branch information
Fanda Vacek committed Feb 29, 2024
1 parent 7db6d9f commit b35183d
Show file tree
Hide file tree
Showing 8 changed files with 312 additions and 6 deletions.
2 changes: 2 additions & 0 deletions quickevent/app/quickevent/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,9 @@ if(WITH_QE_SHVAPI)
plugins/Event/src/services/shvapi/client.cpp
plugins/Event/src/services/shvapi/clientwidget.cpp
plugins/Event/src/services/shvapi/shvnode.cpp
plugins/Event/src/services/shvapi/sqlnode.cpp
plugins/Event/src/services/shvapi/nodes.cpp
plugins/Event/src/services/shvapi/rpcsqlresult.cpp
)
endif()

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "client.h"
#include "clientwidget.h"
#include "nodes.h"
#include "sqlnode.h"

#include "../../eventplugin.h"

Expand Down Expand Up @@ -56,8 +57,9 @@ Client::Client(QObject *parent)
auto *stage = new shv::iotqt::node::ShvNode("stage", event);
for (auto i = 0; i < event_plugin->stageCount(); i++) {
auto *nd = new shv::iotqt::node::ShvNode(std::to_string(i + 1), stage);
new RunNode(i, nd);
new StartListStarterNode(i, nd);
}
new SqlNode(m_rootNode);
}
else {
qDeleteAll(m_rootNode->findChildren<EventNode*>());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ static auto METH_RECORD = "record";
static auto METH_SET_RECORD = "setRecord";
static auto SIG_REC_CHNG = "recchng";

const std::vector<MetaMethod> &RunNode::metaMethods()
const std::vector<MetaMethod> &StartListStarterNode::metaMethods()
{
static std::vector<MetaMethod> meta_methods {
{Rpc::METH_DIR, MetaMethod::Signature::RetParam, MetaMethod::Flag::None, Rpc::ROLE_BROWSE},
Expand All @@ -92,7 +92,7 @@ const std::vector<MetaMethod> &RunNode::metaMethods()
return meta_methods;
}

RpcValue RunNode::callMethod(const StringViewList &shv_path, const std::string &method, const shv::chainpack::RpcValue &params, const shv::chainpack::RpcValue &user_id)
RpcValue StartListStarterNode::callMethod(const StringViewList &shv_path, const std::string &method, const shv::chainpack::RpcValue &params, const shv::chainpack::RpcValue &user_id)
{
qfLogFuncFrame() << shv_path.join('/') << method;
//eyascore::utils::UserId user_id = eyascore::utils::UserId::makeUserName(QString::fromStdString(rq.userId().toMap().value("userName").toString()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,14 @@ class EventNode : public shvapi::ShvNode
shv::chainpack::RpcValue callMethod(const StringViewList &shv_path, const std::string &method, const shv::chainpack::RpcValue &params, const shv::chainpack::RpcValue &user_id) override;
};

class RunNode : public shvapi::ShvNode
class StartListStarterNode : public shvapi::ShvNode
{
Q_OBJECT

using Super = shvapi::ShvNode;
public:
explicit RunNode(int stage, shv::iotqt::node::ShvNode *parent)
: Super("startlist", parent)
explicit StartListStarterNode(int stage, shv::iotqt::node::ShvNode *parent)
: Super("startliststarter", parent)
, m_stage(stage)
{}
private:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
#include "rpcsqlresult.h"

#include <qf/core/log.h>

#include <shv/chainpack/rpcmessage.h>
#include <shv/coreqt/rpc.h>

#include <QDateTime>
#include <QSqlQuery>
#include <QSqlRecord>
#include <QSqlField>

using namespace shv::chainpack;

namespace Event::services::shvapi {

RpcValue RpcSqlField::toRpcValue() const
{
RpcValue::Map ret;
ret["name"] = name.toStdString();
ret["type"] = type;
ret["typeName"] = QMetaType(type).name();
return RpcValue(std::move(ret));
}

QVariant RpcSqlField::toVariant() const
{
QVariantMap ret;
ret["name"] = name;
ret["type"] = type;
ret["typeName"] = QMetaType(type).name();
return ret;
}

RpcSqlField RpcSqlField::fromRpcValue(const shv::chainpack::RpcValue &rv)
{
RpcSqlField ret;
const RpcValue::Map &map = rv.asMap();
ret.name = QString::fromStdString(map.value("name").asString());
ret.type = map.value("type").toInt();
return ret;
}

RpcSqlField RpcSqlField::fromVariant(const QVariant &v)
{
RpcSqlField ret;
const QVariantMap map = v.toMap();
ret.name = map.value("name").toString();
ret.type = map.value("type").toInt();
return ret;
}

RpcSqlResult::RpcSqlResult(const shv::chainpack::RpcResponse &resp)
{
if(resp.isSuccess()) {
const RpcValue::Map result = resp.result().asMap();
for(const RpcValue &rv : result.valref("fields").asList()) {
RpcSqlField fld;
fld.name = QString::fromStdString(rv.asMap().value("name").toString());
fld.type = rv.asMap().value("type").toInt();
fields.append(fld);
}
for(const RpcValue &rowv : result.valref("rows").asList()) {
Row row;
for(const RpcValue &rv : rowv.asList()) {
bool ok;
QVariant v = shv::coreqt::rpc::rpcValueToQVariant(rv, &ok);
if (!ok) {
qfError() << "Cannot convert:" << rv.toCpon() << "to QVariant";
}
row.append(v);
}
rows.insert(rows.count(), row);
}
numRowsAffected = result.value("numRowsAffected").toInt();
lastInsertId = result.value("lastInserId").toInt();
}
else {
lastError = QString::fromStdString(resp.errorString());
}
}

QVariant RpcSqlResult::value(int col, int row) const
{
return rows.value(row).toList().value(col);
}

RpcValue RpcSqlResult::toRpcValue() const
{
return shv::coreqt::rpc::qVariantToRpcValue(toVariant());
}

QVariant RpcSqlResult::toVariant() const
{
QVariantMap ret;
if(isSelect()) {
QVariantList flds;
for(const auto &fld : this->fields)
flds.push_back(fld.toVariant());
ret["fields"] = flds;
ret["rows"] = rows;
}
else {
ret["numRowsAffected"] = numRowsAffected;
ret["lastInsertId"] = lastInsertId;
}
return ret;
}

/*
RpcSqlResult RpcSqlResult::fromRpcValue(const shv::chainpack::RpcValue &rv)
{
RpcSqlResult ret;
const RpcValue::Map &map = rv.asMap();
const RpcValue::List &flds = map.value("fields").asList();
if(flds.empty()) {
ret.numRowsAffected = map.value("numRowsAffected").toInt();
ret.lastInsertId = map.value("lastInsertId").toInt();
}
else {
}
return ret;
}
*/

RpcSqlResult RpcSqlResult::fromVariant(const QVariant &v)
{
RpcSqlResult ret;
const QVariantMap map = v.toMap();
const QVariantList flds = map.value("fields").toList();
if(flds.isEmpty()) {
ret.numRowsAffected = map.value("numRowsAffected").toInt();
ret.lastInsertId = map.value("lastInsertId").toInt();
}
else {
for(const QVariant &fv : flds)
ret.fields.append(RpcSqlField::fromVariant(fv));
ret.rows = map.value("rows").toList();
}
return ret;
}

RpcSqlResult RpcSqlResult::fromRpcValue(const shv::chainpack::RpcValue &rv)
{
auto v = shv::coreqt::rpc::rpcValueToQVariant(rv);
return fromVariant(v);
}

RpcSqlResult RpcSqlResult::fromQuery(QSqlQuery &q)
{
RpcSqlResult ret;
if(q.isSelect()) {
QSqlRecord rec = q.record();
for (int i = 0; i < rec.count(); ++i) {
QSqlField fld = rec.field(i);
RpcSqlField rfld;
rfld.name = fld.name();
rfld.type = fld.metaType().id();
ret.fields.append(rfld);
}
while(q.next()) {
RpcSqlResult::Row row;
for (int i = 0; i < rec.count(); ++i) {
const QVariant v = q.value(i);
if (v.isNull())
row.append(QVariant());
else
row.append(v);
//shvError() << v << v.isNull() << jsv.toVariant() << jsv.toVariant().isNull();
}
ret.rows.insert(ret.rows.count(), row);
}
}
else {
ret.numRowsAffected = q.numRowsAffected();
ret.lastInsertId = q.lastInsertId().toInt();
}
return ret;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#pragma once

#include <QVector>
#include <QVariantList>

namespace shv::chainpack { class RpcResponse; class RpcValue; }

class QSqlQuery;

namespace Event::services::shvapi {

class RpcSqlField
{
public:
QString name;
int type = 0;
public:
//explicit RpcSqlField(const QJsonObject &jo = QJsonObject()) : Super(jo) {}
shv::chainpack::RpcValue toRpcValue() const;
QVariant toVariant() const;
static RpcSqlField fromRpcValue(const shv::chainpack::RpcValue &rv);
static RpcSqlField fromVariant(const QVariant &v);
};

class RpcSqlResult
{
public:
int numRowsAffected = 0;
int lastInsertId = 0;
QString lastError;
QVector<RpcSqlField> fields;
using Row = QVariantList;
QVariantList rows;
public:
explicit RpcSqlResult() = default;
explicit RpcSqlResult(const shv::chainpack::RpcResponse &resp);

QVariant value(int col, int row) const;

bool isSelect() const {return !fields.isEmpty();}
shv::chainpack::RpcValue toRpcValue() const;
QVariant toVariant() const;
//static RpcSqlResult fromRpcValue(const shv::chainpack::RpcValue &rv);
static RpcSqlResult fromVariant(const QVariant &v);
static RpcSqlResult fromRpcValue(const shv::chainpack::RpcValue &rv);
static RpcSqlResult fromQuery(QSqlQuery &q);

};

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#include "sqlnode.h"
#include "rpcsqlresult.h"

#include <qf/core/exception.h>
#include <qf/core/sql/query.h>
#include <qf/core/log.h>

#include <shv/chainpack/rpc.h>
#include <shv/coreqt/rpc.h>

using namespace shv::chainpack;

namespace Event::services::shvapi {

SqlNode::SqlNode(shv::iotqt::node::ShvNode *parent)
: Super("sql", parent)
{

}

static auto METH_EXEC_SQL = "execSql";

const std::vector<MetaMethod> &SqlNode::metaMethods()
{
static std::vector<MetaMethod> meta_methods {
{Rpc::METH_DIR, MetaMethod::Signature::RetParam, MetaMethod::Flag::None, Rpc::ROLE_BROWSE},
{Rpc::METH_LS, MetaMethod::Signature::RetParam, MetaMethod::Flag::None, Rpc::ROLE_BROWSE},
{METH_EXEC_SQL, MetaMethod::Signature::RetVoid, MetaMethod::Flag::None, Rpc::ROLE_WRITE},
};
return meta_methods;
}

RpcValue SqlNode::callMethod(const StringViewList &shv_path, const std::string &method, const shv::chainpack::RpcValue &params, const shv::chainpack::RpcValue &user_id)
{
qfLogFuncFrame() << shv_path.join('/') << method;
//eyascore::utils::UserId user_id = eyascore::utils::UserId::makeUserName(QString::fromStdString(rq.userId().toMap().value("userName").toString()));
if(shv_path.empty()) {
if(method == METH_EXEC_SQL) {
qf::core::sql::Query q;
QString qs = params.to<QString>();
q.exec(qs, qf::core::Exception::Throw);
auto res = RpcSqlResult::fromQuery(q);
return res.toRpcValue();
}
}
return Super::callMethod(shv_path, method, params, user_id);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#pragma once

#include "shvnode.h"

namespace Event::services::shvapi {

class SqlNode : public ShvNode
{
Q_OBJECT

using Super = ShvNode;
public:
explicit SqlNode(shv::iotqt::node::ShvNode *parent);

protected:
const std::vector<shv::chainpack::MetaMethod> &metaMethods() override;
shv::chainpack::RpcValue callMethod(const StringViewList &shv_path, const std::string &method, const shv::chainpack::RpcValue &params, const shv::chainpack::RpcValue &user_id) override;
};

}

0 comments on commit b35183d

Please sign in to comment.