droplet 1.1.0
A multipurpose Discord bot with the hacker in mind
Loading...
Searching...
No Matches
Database.hpp
Go to the documentation of this file.
1/*
2 * (c) Copyright dropsoft.org - All rights reserved
3 * Author: Erarnitox <david@erarnitox.de>
4 *
5 * License: MIT License
6 *
7 * Description: This class manages Database access
8 * and provides a high level API for internal use
9 *
10 * Documentation: https://droplet.erarnitox.de/doxygen/html/database
11 */
12
13#pragma once
14
15#include <cstddef>
16// #include <iostream>
17#include <pqxx/pqxx>
18#include <string>
19#include <variant>
20#include <vector>
21// #include <format>
22
23#include "RowDTOAdapter.hpp"
24
25class Database {
26 public:
27 Database() = delete;
28
29 [[nodiscard]] static auto connect(const std::string& db_name,
30 const std::string& user,
31 const std::string& password,
32 const std::string& host,
33 const std::string& port) -> bool;
34
35 [[nodiscard]] static auto connect(const std::string& connection_string) -> bool;
36
37 static auto hasConnection() noexcept -> bool;
38 static auto reconnect() noexcept -> void;
39 static auto disconnect() noexcept -> void;
40 static auto getConnection() noexcept -> pqxx::connection*;
41};
42
43namespace database {
44
45// Compile time "for" loop
46template <size_t I = 0, typename... Types>
47constexpr void assignResults(const pqxx::result& result, std::vector<std::variant<Types...>>& args) {
48 if constexpr (I < sizeof...(Types)) {
49 args[I] = result.at(0, I).template get<std::variant_alternative_t<I, std::variant<Types...>>>().value();
50 assignResults<I + 1>(result, args);
51 }
52}
53
61template <typename... Types>
62[[nodiscard("You need to check if the Query was executed on the Database!")]] auto execQuery(const std::string& query,
63 Types&&... args) noexcept
64 -> bool {
65 static int times = 0;
66 try {
67 pqxx::work txn(*Database::getConnection());
68
69 // perform the database transaction
70 pqxx::result result = txn.exec_params(query, std::forward<Types>(args)...);
71 txn.commit();
72
73 times = 0;
74 return true;
75 } catch (const pqxx::broken_connection& e) {
76 ++times;
77 if (times > 10) {
78 times = 0;
79 return false;
80 }
82 return execQuery(query, args...);
83 } catch (...) {
84 // std::cout << std::format("Invalid exec for query:{}\n", query);
85 return false;
86 }
87}
88
96template <typename... Types>
97[[nodiscard]] auto execSelect(const std::string& query, Types&&... args) noexcept -> RowDTOAdapter {
98 static int times = 0;
99 try {
100 pqxx::work txn(*Database::getConnection());
101
102 // perform the database transaction
103 pqxx::result result = txn.exec_params(query, std::forward<Types>(args)...);
104 txn.commit();
105
106 times = 0;
107
108 return {result[0]};
109 } catch (const pqxx::broken_connection& e) {
110 ++times;
111 if (times > 10) {
112 times = 0;
113 return {pqxx::row()};
114 }
116 return execSelect(query, args...);
117 } catch (...) {
118 // std::cout << std::format("Invalid selection for query: {}\n", query);
119 return {{}}; // return an empty selection
120 }
121}
122
130template <typename... Types>
131[[nodiscard]] auto execSelectAll(const std::string& query, Types&&... args) noexcept -> std::vector<RowDTOAdapter> {
132 static int times = 0;
133 try {
134 pqxx::work txn(*Database::getConnection());
135
136 // perform the database transaction
137 pqxx::result result = txn.exec_params(query, std::forward<Types>(args)...);
138 txn.commit();
139
140 times = 0;
141
142 std::vector<RowDTOAdapter> selection;
143 for (int i{0}; i < result.size(); ++i) {
144 selection.emplace_back(result[i]);
145 }
146
147 return selection;
148 } catch (const pqxx::broken_connection& e) {
149 ++times;
150 if (times > 10) {
151 times = 0;
152 return {pqxx::row()};
153 }
155 return execSelectAll(query, args...);
156 } catch (...) {
157 // std::cout << std::format("Invalid selection for query: {}\n", query);
158 return {{}}; // return an empty selection
159 }
160}
161} // namespace database
Definition Database.hpp:25
static auto getConnection() noexcept -> pqxx::connection *
returns the database connection. Reconnects if the Database has no active connection
Definition Database.cpp:108
static auto reconnect() noexcept -> void
reconnects to the database server if the connection was lost
Definition Database.cpp:79
static auto disconnect() noexcept -> void
disconnect from a postgres database
Definition Database.cpp:61
static auto hasConnection() noexcept -> bool
checks if the database has an active connection
Definition Database.cpp:69
static auto connect(const std::string &db_name, const std::string &user, const std::string &password, const std::string &host, const std::string &port) -> bool
connect to a postgres database
Definition Database.cpp:33
Database()=delete
Definition RowDTOAdapter.hpp:20
Definition Database.hpp:43
auto execSelect(const std::string &query, Types &&... args) noexcept -> RowDTOAdapter
executes a Select on the database
Definition Database.hpp:97
auto execSelectAll(const std::string &query, Types &&... args) noexcept -> std::vector< RowDTOAdapter >
executes a Select on the database
Definition Database.hpp:131
constexpr void assignResults(const pqxx::result &result, std::vector< std::variant< Types... > > &args)
Definition Database.hpp:47
auto execQuery(const std::string &query, Types &&... args) noexcept -> bool
executes a query on the database
Definition Database.hpp:62