From 74a707f938a7ca778c88a2717bfe5b5ab4aa5230 Mon Sep 17 00:00:00 2001 From: Tina_Azure <-> Date: Mon, 20 Mar 2023 18:06:51 +0100 Subject: [PATCH] Database Manager namespace Implementations: struct representing an Requests Item with the apropriate JSON parser a generic sql execution ideally something that is not necessary prepared statment for the insertion of an item into Requests prepared statment for the read out of Requests based on the ID conversion of a pqxx::result into a wvalue JSON which is usable by the crowcpp context --- .gitignore | 3 ++ src/database.cpp | 123 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 126 insertions(+) create mode 100644 src/database.cpp diff --git a/.gitignore b/.gitignore index d71fcf7..9751548 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ ## C++ shit /bin cavecomm +.idea/.gitignore +.idea/misc.xml +.idea/vcs.xml diff --git a/src/database.cpp b/src/database.cpp new file mode 100644 index 0000000..5ca3d9e --- /dev/null +++ b/src/database.cpp @@ -0,0 +1,123 @@ +#include +#include +#include +#include +#include +#include "crow.h" + + +/* + * Database Manager + */ +namespace Database { + //Valid names for the JSON + const static std::string JSON_ITEM_NAMES[] = {"id", "customerEmailAddress", "freelancer", "templateName", "currencyPreference", "priceUpFront", "priceOnDeliver", "requestDescription", "accepted", "upFrontInvoiceID", "onDeliverInvoiceID", "upFrontPaid", "onDeliverPaid"}; + + //Name and Statement for prepared statement to insert an item into Requests + const static std::string PREPARED_STATEMENT_INSERT_ITEM_IN_REQUESTS = "insertItemInRequests"; + const static std::string SQL_STATEMENT_INSERT_ITEM_IN_REQUESTS = "INSERT INTO requests(id, customerEmailAddress, freelancer, templateName, currencyPreference, priceUpFront, priceOnDeliver, requestDescription, accepted, upFrontInvoiceID, onDeliverInvoiceID, upFrontPaid, onDeliverPaid) VALUES(DEFAULT, $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12 );"; + /* + * Name and Statement for prepared statement to select an item based on a given ID + * Case for boolean return values because the default return value is f/t instead of 0/1 or false/true + */ + const static std::string PREPARED_STATEMENT_SELECT_ITEM_BY_ID = "selectItemByID"; + const static std::string SQL_STATEMENT_SELECT_ITEM_BY_ID = "SELECT id , customerEmailAddress, freelancer, templateName, currencyPreference, priceUpFront, priceOnDeliver, requestDescription, (CASE WHEN requests.accepted THEN 1 ELSE 0 END) AS accepted, upFrontInvoiceID, onDeliverInvoiceID, (CASE WHEN requests.upFrontPaid THEN 1 ELSE 0 END) AS upFrontPaid, (CASE WHEN requests.onDeliverPaid THEN 1 ELSE 0 END) AS onDeliverPaid FROM requests WHERE id=$1;"; + + /* + * Struct Representing an item in Requests + */ + struct requestsItem { + int id; + std::string customerEmailAddress; + std::string freelancer; + std::string templateName; + std::string currencyPreference; + std::string priceUpFront; + std::string priceOnDeliver; + std::string requestDescription; + bool accepted; + std::string upFrontInvoiceID; + std::string onDeliverInvoiceID; + bool upFrontPaid; + bool onDeliverPaid; + + /* + * Parses a JSON and fills the Item with the delivered values + */ + void insertJsonIntoItem(crow::json::rvalue itemJson){ + if (itemJson.has(JSON_ITEM_NAMES[0])) id = itemJson[JSON_ITEM_NAMES[0]].i(); + if (itemJson.has(JSON_ITEM_NAMES[1])) customerEmailAddress = itemJson[JSON_ITEM_NAMES[1]].s(); + if (itemJson.has(JSON_ITEM_NAMES[2])) freelancer = itemJson[JSON_ITEM_NAMES[2]].s(); + if (itemJson.has(JSON_ITEM_NAMES[3])) templateName = itemJson[JSON_ITEM_NAMES[3]].s(); + if (itemJson.has(JSON_ITEM_NAMES[4])) currencyPreference = itemJson[JSON_ITEM_NAMES[4]].s(); + if (itemJson.has(JSON_ITEM_NAMES[5])) priceUpFront = itemJson[JSON_ITEM_NAMES[5]].s(); + if (itemJson.has(JSON_ITEM_NAMES[6])) priceOnDeliver = itemJson[JSON_ITEM_NAMES[6]].s(); + if (itemJson.has(JSON_ITEM_NAMES[7])) requestDescription = itemJson[JSON_ITEM_NAMES[7]].s(); + if (itemJson.has(JSON_ITEM_NAMES[8])) accepted = itemJson[JSON_ITEM_NAMES[8]].b(); + if (itemJson.has(JSON_ITEM_NAMES[9])) upFrontInvoiceID = itemJson[JSON_ITEM_NAMES[9]].s(); + if (itemJson.has(JSON_ITEM_NAMES[10])) onDeliverInvoiceID = itemJson[JSON_ITEM_NAMES[10]].s(); + if (itemJson.has(JSON_ITEM_NAMES[11])) upFrontPaid = itemJson[JSON_ITEM_NAMES[11]].b(); + if (itemJson.has(JSON_ITEM_NAMES[12])) onDeliverPaid = itemJson[JSON_ITEM_NAMES[12]].b(); + } + }; + + /* + * Executes an SQL query and returns results + * Takes an open pqxx::connection + */ + pqxx::result executeSQL(pqxx::connection &connection, std::string sqlQuery) { + pqxx::work work(connection); + pqxx::result result = work.exec(sqlQuery); + work.commit(); + return result; + } + + /* + * Executes the prepared statement INSERT_ITEM_IN_REQUESTS + * Takes an open pqxx::connection and the requestsItem to insert + */ + pqxx::result executePreparedStatement_INSERT_ITEM_IN_REQUESTS(pqxx::connection &connection, requestsItem item) { + connection.prepare(PREPARED_STATEMENT_INSERT_ITEM_IN_REQUESTS, SQL_STATEMENT_INSERT_ITEM_IN_REQUESTS); + pqxx::work work(connection); + pqxx::result result = work.exec_prepared(PREPARED_STATEMENT_INSERT_ITEM_IN_REQUESTS, + item.customerEmailAddress, item.freelancer, item.templateName, + item.currencyPreference, item.priceUpFront, item.priceOnDeliver, + item.requestDescription, item.accepted, item.upFrontInvoiceID, + item.onDeliverInvoiceID, item.upFrontPaid, item.onDeliverPaid); + work.commit(); + return result; + } + + /* + * Executes the prepared statement SELECT_ITEM_BY_ID + * Takes an open pqxx::connection and the id to select by + */ + pqxx::result executePreparedStatement_SELECT_ITEM_BY_ID(pqxx::connection &connection, int id) { + connection.prepare(PREPARED_STATEMENT_SELECT_ITEM_BY_ID, SQL_STATEMENT_SELECT_ITEM_BY_ID); + pqxx::work work(connection); + pqxx::result result = work.exec_prepared(PREPARED_STATEMENT_SELECT_ITEM_BY_ID, id); + work.commit(); + return result; + } + + /* + * parses the result and returns a JSON + * Takes a result and optionally the desired row + * !the result delivers only lowercase column names, either the templates are appropriately changed + * or a validation is performed at conversion. + */ + crow::json::wvalue convertResultRowToJSON(pqxx::result &result, int row = 0){ + crow::json::wvalue returnJson; + for (int i = 0; i < result.columns(); ++i) { + std::string realColName = result.column_name(i); + for (std::string columnNameReal: JSON_ITEM_NAMES) { + if (boost::algorithm::to_lower_copy(columnNameReal) == realColName) { + realColName = columnNameReal; + break; + } + } + returnJson[realColName] = result.at(row).at(i).c_str(); + } + return returnJson; + } +} \ No newline at end of file