The Battle for Wesnoth  1.15.9+dev
dbconn.hpp
Go to the documentation of this file.
1 /*
2  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
3 
4  This program is free software; you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation; either version 2 of the License, or
7  (at your option) any later version.
8  This program is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY.
10 
11  See the COPYING file for more details.
12 */
13 
14 #pragma once
15 
16 #include "config.hpp"
20 
21 #include <mysql/mysql.h>
22 #include "mariadb++/account.hpp"
23 #include "mariadb++/connection.hpp"
24 #include "mariadb++/statement.hpp"
25 #include "mariadb++/result_set.hpp"
26 #include "mariadb++/exceptions.hpp"
27 
28 #include <vector>
29 #include <unordered_map>
30 
31 /**
32  * This class is responsible for handling the database connections as well as executing queries and handling any results.
33  * @note The account and connection should never ever be provided to anything outside of this class.
34  * @note !DO NOT APPEND VALUES DIRECTLY TO THE SQL TEXT IN ANY QUERY!
35  */
36 class dbconn
37 {
38  public:
39  /**
40  * Initializes the synchronous query connection as well as the account object that has the connection settings.
41  *
42  * @param c The config object to read information from.
43  */
44  dbconn(const config& c);
45 
46  /**
47  * @see forum_user_handler::async_test_query().
48  */
49  int async_test_query(int limit);
50 
51  /**
52  * @see forum_user_handler::get_uuid().
53  */
54  std::string get_uuid();
55 
56  /**
57  * @see forum_user_handler::get_tournaments().
58  */
59  std::string get_tournaments();
60 
61  /**
62  * This is an asynchronous query that is executed on a separate connection to retrieve the game history for the provided player.
63  *
64  * @param player_id The forum ID of the player to get the game history for.
65  * @param offset The offset to provide to the database for where to start returning rows from.
66  * @return The simple_wml document containing the query results, or simply the @a error attribute if an exception is thrown.
67  */
68  std::unique_ptr<simple_wml::document> get_game_history(int player_id, int offset);
69 
70  /**
71  * @see forum_user_handler::user_exists().
72  */
73  bool user_exists(const std::string& name);
74 
75  /**
76  * @see forum_user_handler::get_forum_id().
77  */
78  long get_forum_id(const std::string& name);
79 
80  /**
81  * @param name The player's username.
82  * @return Whether the player has a row in the extra table.
83  */
84  bool extra_row_exists(const std::string& name);
85 
86  /**
87  * @see forum_user_handler::is_user_in_group().
88  */
89  bool is_user_in_group(const std::string& name, int group_id);
90 
91  /**
92  * @param table The table that will be queried.
93  * @param column The column that will be selected.
94  * @param name The player's username.
95  * @return The string value in the provided table and column for the provided username.
96  */
97  std::string get_user_string(const std::string& table, const std::string& column, const std::string& name);
98 
99  /**
100  * @param table The table that will be queried.
101  * @param column The column that will be selected.
102  * @param name The player's username.
103  * @return The int value in the provided table and column for the provided username.
104  */
105  int get_user_int(const std::string& table, const std::string& column, const std::string& name);
106 
107  /**
108  * The provided value is updated if a row exists or a new row inserted otherwise.
109  *
110  * @param column The column that the value will be put into.
111  * @param name The player's username.
112  * @param value The value to be put into the column.
113  */
114  void write_user_int(const std::string& column, const std::string& name, int value);
115 
116  /**
117  * @see forum_user_handler::user_is_banned().
118  */
119  ban_check get_ban_info(const std::string& name, const std::string& ip);
120 
121  /**
122  * @see forum_user_handler::db_insert_game_info().
123  */
124  void insert_game_info(const std::string& uuid, int game_id, const std::string& version, const std::string& name, int reload, int observers, int is_public, int has_password);
125 
126  /**
127  * @see forum_user_handler::db_update_game_end().
128  */
129  void update_game_end(const std::string& uuid, int game_id, const std::string& replay_location);
130 
131  /**
132  * @see forum_user_handler::db_insert_game_player_info().
133  */
134  void insert_game_player_info(const std::string& uuid, int game_id, const std::string& username, int side_number, int is_host, const std::string& faction, const std::string& version, const std::string& source, const std::string& current_user);
135 
136  /**
137  * @see forum_user_handler::db_insert_game_content_info().
138  */
139  void insert_game_content_info(const std::string& uuid, int game_id, const std::string& type, const std::string& name, const std::string& id, const std::string& source, const std::string& version);
140 
141  /**
142  * @see forum_user_handler::db_set_oos_flag().
143  */
144  void set_oos_flag(const std::string& uuid, int game_id);
145 
146  private:
147  /**
148  * The account used to connect to the database.
149  * Also contains the connection settings.
150  * @note settings put on the connection, rather than the account, are NOT kept if a reconnect occurs!
151  */
152  mariadb::account_ref account_;
153  /** The actual connection to the database. */
154  mariadb::connection_ref connection_;
155 
156  /** The name of the table that contains forum user information. */
157  std::string db_users_table_;
158  /** The name of the table that contains forum ban information. */
159  std::string db_banlist_table_;
160  /** The name of the table that contains additional user information. */
161  std::string db_extra_table_;
162  /** The name of the table that contains game-level information. */
163  std::string db_game_info_table_;
164  /** The name of the table that contains player-level information per game. */
166  /** The name of the table that contains game content information. */
168  /** The name of the table that contains forum group information. */
169  std::string db_user_group_table_;
170  /** The text of the SQL query to use to retrieve any currently active tournaments. */
171  std::string db_tournament_query_;
172 
173  /**
174  * This is used to write out error text when an SQL-related exception occurs.
175  *
176  * @param text Some custom text to log.
177  * @param e The exception that occurred which has information about what went wrong.
178  */
179  void log_sql_exception(const std::string& text, const mariadb::exception::base& e);
180 
181  /**
182  * Creates a new connection object from the account.
183  */
184  mariadb::connection_ref create_connection();
185 
186  /**
187  * Queries can return data with various types that can't be easily fit into a pre-determined structure.
188  * Therefore for queries that can return multiple rows with multiple columns, a class that extends @ref rs_base handles reading the results.
189  *
190  * @param connection The database connecion that will be used to execute the query.
191  * @param base The class that will handle reading the results.
192  * @param sql The SQL text to be executed.
193  * @param args The parameterized values to be inserted into the query.
194  */
195  template<typename... Args>
196  void get_complex_results(mariadb::connection_ref connection, rs_base& base, const std::string& sql, Args&&... args);
197 
198  /**
199  * @param connection The database connecion that will be used to execute the query.
200  * @param sql The SQL text to be executed.
201  * @param args The parameterized values to be inserted into the query.
202  * @return The single string value queried.
203  * @throws mariadb::exception::base when the query finds no value to be retrieved.
204  */
205  template<typename... Args>
206  std::string get_single_string(mariadb::connection_ref connection, const std::string& sql, Args&&... args);
207 
208  /**
209  * @param connection The database connecion that will be used to execute the query.
210  * @param sql The SQL text to be executed.
211  * @param args The parameterized values to be inserted into the query.
212  * @return The single long value queried.
213  * @throws mariadb::exception::base when the query finds no value to be retrieved.
214  */
215  template<typename... Args>
216  long get_single_long(mariadb::connection_ref connection, const std::string& sql, Args&&... args);
217 
218  /**
219  * @param connection The database connecion that will be used to execute the query.
220  * @param sql The SQL text to be executed.
221  * @param args The parameterized values to be inserted into the query.
222  * @return True if any data was returned by the query, otherwise false.
223  */
224  template<typename... Args>
225  bool exists(mariadb::connection_ref connection, const std::string& sql, Args&&... args);
226 
227  /**
228  * Executes a select statement.
229  *
230  * @param connection The database connecion that will be used to execute the query.
231  * @param sql The SQL text to be executed.
232  * @param args The parameterized values to be inserted into the query.
233  * @return A result set containing the results of the select statement executed.
234  */
235  template<typename... Args>
236  mariadb::result_set_ref select(mariadb::connection_ref connection, const std::string& sql, Args&&... args);
237 
238  /**
239  * Executes non-select statements (ie: insert, update, delete).
240  *
241  * @param connection The database connecion that will be used to execute the query.
242  * @param sql The SQL text to be executed.
243  * @param args The parameterized values to be inserted into the query.
244  * @return The number of rows modified.
245  */
246  template<typename... Args>
247  int modify(mariadb::connection_ref connection, const std::string& sql, Args&&... args);
248 
249  /**
250  * Begins recursively unpacking of the parameter pack in order to be able to call the correct parameterized setters on the query.
251  *
252  * @param connection The database connecion that will be used to execute the query.
253  * @param sql The SQL text to be executed.
254  * @param args The parameterized values to be inserted into the query.
255  * @return A statement object with all parameterized values added. This will then be executed by either @ref modify() or @ref select().
256  */
257  template<typename... Args>
258  mariadb::statement_ref query(mariadb::connection_ref connection, const std::string& sql, Args&&... args);
259 
260  /**
261  * The next parameter to be added is split off from the parameter pack.
262  *
263  * @param stmt The statement that will have parameterized values set on it.
264  * @param i The index of the current parameterized value.
265  * @param arg The next parameter to be added.
266  * @param args The remaining parameters to be added.
267  */
268  template<typename Arg, typename... Args>
269  void prepare(mariadb::statement_ref stmt, int i, Arg arg, Args&&... args);
270 
271  /**
272  * Specializations for each type of value to be parameterized.
273  * There are other parameter setters than those currently implemented, but so far there hasn't been a reason to add them.
274  *
275  * @param stmt The statement that will have parameterized values set on it.
276  * @param i The index of the current parameterized value.
277  * @param arg The next parameter to be added.
278  * @return The index of the next parameter to add.
279  */
280  template<typename Arg>
281  int prepare(mariadb::statement_ref stmt, int i, Arg arg);
282 
283  /**
284  * Nothing left to parameterize, so break out of the recursion.
285  */
286  void prepare(mariadb::statement_ref stmt, int i);
287 };
std::string db_tournament_query_
The text of the SQL query to use to retrieve any currently active tournaments.
Definition: dbconn.hpp:171
void prepare(mariadb::statement_ref stmt, int i, Arg arg, Args &&... args)
The next parameter to be added is split off from the parameter pack.
int async_test_query(int limit)
std::string get_user_string(const std::string &table, const std::string &column, const std::string &name)
std::string db_game_info_table_
The name of the table that contains game-level information.
Definition: dbconn.hpp:163
std::string get_tournaments()
void insert_game_info(const std::string &uuid, int game_id, const std::string &version, const std::string &name, int reload, int observers, int is_public, int has_password)
std::string db_banlist_table_
The name of the table that contains forum ban information.
Definition: dbconn.hpp:159
void get_complex_results(mariadb::connection_ref connection, rs_base &base, const std::string &sql, Args &&... args)
Queries can return data with various types that can&#39;t be easily fit into a pre-determined structure...
int get_user_int(const std::string &table, const std::string &column, const std::string &name)
Definitions for the interface to Wesnoth Markup Language (WML).
std::string get_single_string(mariadb::connection_ref connection, const std::string &sql, Args &&... args)
mariadb::connection_ref create_connection()
Creates a new connection object from the account.
This class is responsible for handling the database connections as well as executing queries and hand...
Definition: dbconn.hpp:36
dbconn(const config &c)
Initializes the synchronous query connection as well as the account object that has the connection se...
mariadb::connection_ref connection_
The actual connection to the database.
Definition: dbconn.hpp:154
void write_user_int(const std::string &column, const std::string &name, int value)
The provided value is updated if a row exists or a new row inserted otherwise.
void insert_game_content_info(const std::string &uuid, int game_id, const std::string &type, const std::string &name, const std::string &id, const std::string &source, const std::string &version)
mariadb::account_ref account_
The account used to connect to the database.
Definition: dbconn.hpp:152
long get_single_long(mariadb::connection_ref connection, const std::string &sql, Args &&... args)
bool is_user_in_group(const std::string &name, int group_id)
std::string db_game_player_info_table_
The name of the table that contains player-level information per game.
Definition: dbconn.hpp:165
std::string db_game_content_info_table_
The name of the table that contains game content information.
Definition: dbconn.hpp:167
std::string get_uuid()
std::size_t i
Definition: function.cpp:933
void set_oos_flag(const std::string &uuid, int game_id)
bool user_exists(const std::string &name)
std::string name
Definition: sdl_ttf.cpp:70
std::unique_ptr< simple_wml::document > get_game_history(int player_id, int offset)
This is an asynchronous query that is executed on a separate connection to retrieve the game history ...
std::string db_user_group_table_
The name of the table that contains forum group information.
Definition: dbconn.hpp:169
long get_forum_id(const std::string &name)
int modify(mariadb::connection_ref connection, const std::string &sql, Args &&... args)
Executes non-select statements (ie: insert, update, delete).
mariadb::statement_ref query(mariadb::connection_ref connection, const std::string &sql, Args &&... args)
Begins recursively unpacking of the parameter pack in order to be able to call the correct parameteri...
void log_sql_exception(const std::string &text, const mariadb::exception::base &e)
This is used to write out error text when an SQL-related exception occurs.
std::string db_users_table_
The name of the table that contains forum user information.
Definition: dbconn.hpp:157
void insert_game_player_info(const std::string &uuid, int game_id, const std::string &username, int side_number, int is_host, const std::string &faction, const std::string &version, const std::string &source, const std::string &current_user)
mariadb::result_set_ref select(mariadb::connection_ref connection, const std::string &sql, Args &&... args)
Executes a select statement.
#define e
int side_number
Definition: game_info.hpp:39
ban_check get_ban_info(const std::string &name, const std::string &ip)
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:59
mock_char c
std::string db_extra_table_
The name of the table that contains additional user information.
Definition: dbconn.hpp:161
void update_game_end(const std::string &uuid, int game_id, const std::string &replay_location)
bool extra_row_exists(const std::string &name)
bool exists(mariadb::connection_ref connection, const std::string &sql, Args &&... args)