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 erarnitox.de - 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 <iostream>
18#include <pqxx/pqxx>
19#include <string>
20#include <variant>
21#include <vector>
22// #include <format>
23
24#include "RowDTOAdapter.hpp"
25
26class Database {
27 public:
28 Database() = delete;
29
30 [[nodiscard]] static auto connect(const std::string& db_name,
31 const std::string& user,
32 const std::string& password,
33 const std::string& host,
34 const std::string& port) -> bool;
35
36 [[nodiscard]] static auto connect(const std::string& connection_string) -> bool;
37
38 static auto hasConnection() noexcept -> bool;
39 static auto reconnect() noexcept -> void;
40 static auto disconnect() noexcept -> void;
41 static auto getConnection() noexcept -> pqxx::connection*;
42};
43
44namespace database {
45
46// Compile time "for" loop
47template <size_t I = 0, typename... Types>
48constexpr void assignResults(const pqxx::result& result, std::vector<std::variant<Types...>>& args) {
49 if constexpr (I < sizeof...(Types)) {
50 args[I] = result.at(0, I).template get<std::variant_alternative_t<I, std::variant<Types...>>>().value();
51 assignResults<I + 1>(result, args);
52 }
53}
54
62template <typename... Types>
63[[nodiscard("You need to check if the Query was executed on the Database!")]] auto execQuery(const std::string& query,
64 Types&&... args) noexcept
65 -> bool {
66 static int times = 0;
67 try {
68 pqxx::work txn(*Database::getConnection());
69
70 // perform the database transaction
71 pqxx::result result = txn.exec_params(query, std::forward<Types>(args)...);
72 txn.commit();
73
74 times = 0;
75 return true;
76 } catch (const pqxx::broken_connection& e) {
77 ++times;
78 if (times > 10) {
79 times = 0;
80 return false;
81 }
83 return execQuery(query, args...);
84 } catch (const std::exception& e) {
85 std::cerr << "Error: " << e.what() << "\nInvalid exec for query:\n" << query << std::endl;
86 return false;
87 }
88}
89
97template <typename... Types>
98[[nodiscard]] auto execSelect(const std::string& query, Types&&... args) noexcept -> RowDTOAdapter {
99 static int times = 0;
100 try {
101 pqxx::work txn(*Database::getConnection());
102
103 // perform the database transaction
104 pqxx::result result = txn.exec_params(query, std::forward<Types>(args)...);
105 txn.commit();
106
107 times = 0;
108
109 return {result[0]};
110 } catch (const pqxx::broken_connection& e) {
111 ++times;
112 if (times > 10) {
113 times = 0;
114 return {pqxx::row()};
115 }
117 return execSelect(query, args...);
118 } catch (const std::exception& e) {
119 std::cerr << "Error: " << e.what() << "\nInvalid selection for query:\n" << query << std::endl;
120 return {{}}; // return an empty selection
121 }
122}
123
131template <typename... Types>
132[[nodiscard]] auto execSelectAll(const std::string& query, Types&&... args) noexcept -> std::vector<RowDTOAdapter> {
133 static int times = 0;
134 try {
135 pqxx::work txn(*Database::getConnection());
136
137 // perform the database transaction
138 pqxx::result result = txn.exec_params(query, std::forward<Types>(args)...);
139 txn.commit();
140
141 times = 0;
142
143 std::vector<RowDTOAdapter> selection;
144 for (int i{0}; i < result.size(); ++i) {
145 selection.emplace_back(result[i]);
146 }
147
148 return selection;
149 } catch (const pqxx::broken_connection& e) {
150 ++times;
151 if (times > 10) {
152 times = 0;
153 return {pqxx::row()};
154 }
156 return execSelectAll(query, args...);
157 } catch (const std::exception& e) {
158 std::cerr << "Error: " << e.what() << "\nInvalid selection for query:\n" << query << std::endl;
159 return {{}}; // return an empty selection
160 }
161}
162} // namespace database
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:44
auto execSelect(const std::string &query, Types &&... args) noexcept -> RowDTOAdapter
executes a Select on the database
Definition Database.hpp:98
auto execSelectAll(const std::string &query, Types &&... args) noexcept -> std::vector< RowDTOAdapter >
executes a Select on the database
Definition Database.hpp:132
constexpr void assignResults(const pqxx::result &result, std::vector< std::variant< Types... > > &args)
Definition Database.hpp:48
auto execQuery(const std::string &query, Types &&... args) noexcept -> bool
executes a query on the database
Definition Database.hpp:63