The Battle for Wesnoth  1.15.12+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  /**
147  * @see forum_user_handler::db_topic_id_exists().
148  */
149  bool topic_id_exists(int topic_id);
150 
151  /**
152  * @see forum_user_handler::db_insert_addon_info().
153  */
154  void insert_addon_info(const std::string& instance_version, const std::string& id, const std::string& name, const std::string& type, const std::string& version, bool forum_auth, int topic_id);
155 
156  /**
157  * @see forum_user_handler::db_insert_login().
158  */
159  unsigned long long insert_login(const std::string& username, const std::string& ip, const std::string& version);
160 
161  /**
162  * @see forum_user_handler::db_update_logout().
163  */
164  void update_logout(unsigned long long login_id);
165 
166  /**
167  * @see forum_user_handler::get_users_for_ip().
168  */
169  void get_users_for_ip(const std::string& ip, std::ostringstream* out);
170 
171  /**
172  * @see forum_user_handler::get_ips_for_users().
173  */
174  void get_ips_for_user(const std::string& username, std::ostringstream* out);
175 
176  private:
177  /**
178  * The account used to connect to the database.
179  * Also contains the connection settings.
180  * @note settings put on the connection, rather than the account, are NOT kept if a reconnect occurs!
181  */
182  mariadb::account_ref account_;
183  /** The actual connection to the database. */
184  mariadb::connection_ref connection_;
185 
186  /** The name of the table that contains forum user information. */
187  std::string db_users_table_;
188  /** The name of the table that contains forum ban information. */
189  std::string db_banlist_table_;
190  /** The name of the table that contains additional user information. */
191  std::string db_extra_table_;
192  /** The name of the table that contains game-level information. */
193  std::string db_game_info_table_;
194  /** The name of the table that contains player-level information per game. */
196  /** The name of the table that contains game content information. */
198  /** The name of the table that contains forum group information. */
199  std::string db_user_group_table_;
200  /** The text of the SQL query to use to retrieve any currently active tournaments. */
201  std::string db_tournament_query_;
202  /** The name of the table that contains phpbb forum thread information */
203  std::string db_topics_table_;
204  /** The name of the table that contains add-on information. */
205  std::string db_addon_info_table_;
206  /** The name of the table that contains user connection history. */
208 
209  /**
210  * This is used to write out error text when an SQL-related exception occurs.
211  *
212  * @param text Some custom text to log.
213  * @param e The exception that occurred which has information about what went wrong.
214  */
215  void log_sql_exception(const std::string& text, const mariadb::exception::base& e);
216 
217  /**
218  * Creates a new connection object from the account.
219  */
220  mariadb::connection_ref create_connection();
221 
222  /**
223  * Queries can return data with various types that can't be easily fit into a pre-determined structure.
224  * Therefore for queries that can return multiple rows with multiple columns, a class that extends @ref rs_base handles reading the results.
225  *
226  * @param connection The database connecion that will be used to execute the query.
227  * @param base The class that will handle reading the results.
228  * @param sql The SQL text to be executed.
229  * @param args The parameterized values to be inserted into the query.
230  */
231  template<typename... Args>
232  void get_complex_results(mariadb::connection_ref connection, rs_base& base, const std::string& sql, Args&&... args);
233 
234  /**
235  * @param connection The database connecion that will be used to execute the query.
236  * @param sql The SQL text to be executed.
237  * @param args The parameterized values to be inserted into the query.
238  * @return The single string value queried.
239  * @throws mariadb::exception::base when the query finds no value to be retrieved.
240  */
241  template<typename... Args>
242  std::string get_single_string(mariadb::connection_ref connection, const std::string& sql, Args&&... args);
243 
244  /**
245  * @param connection The database connecion that will be used to execute the query.
246  * @param sql The SQL text to be executed.
247  * @param args The parameterized values to be inserted into the query.
248  * @return The single long value queried.
249  * @throws mariadb::exception::base when the query finds no value to be retrieved.
250  */
251  template<typename... Args>
252  long get_single_long(mariadb::connection_ref connection, const std::string& sql, Args&&... args);
253 
254  /**
255  * @param connection The database connecion that will be used to execute the query.
256  * @param sql The SQL text to be executed.
257  * @param args The parameterized values to be inserted into the query.
258  * @return True if any data was returned by the query, otherwise false.
259  */
260  template<typename... Args>
261  bool exists(mariadb::connection_ref connection, const std::string& sql, Args&&... args);
262 
263  /**
264  * Executes a select statement.
265  *
266  * @param connection The database connecion that will be used to execute the query.
267  * @param sql The SQL text to be executed.
268  * @param args The parameterized values to be inserted into the query.
269  * @return A result set containing the results of the select statement executed.
270  */
271  template<typename... Args>
272  mariadb::result_set_ref select(mariadb::connection_ref connection, const std::string& sql, Args&&... args);
273 
274  /**
275  * Executes non-select statements (ie: insert, update, delete).
276  *
277  * @param connection The database connecion that will be used to execute the query.
278  * @param sql The SQL text to be executed.
279  * @param args The parameterized values to be inserted into the query.
280  * @return The number of rows modified.
281  */
282  template<typename... Args>
283  unsigned long long modify(mariadb::connection_ref connection, const std::string& sql, Args&&... args);
284 
285  /**
286  * Begins recursively unpacking of the parameter pack in order to be able to call the correct parameterized setters on the query.
287  *
288  * @param connection The database connecion that will be used to execute the query.
289  * @param sql The SQL text to be executed.
290  * @param args The parameterized values to be inserted into the query.
291  * @return A statement object with all parameterized values added. This will then be executed by either @ref modify() or @ref select().
292  */
293  template<typename... Args>
294  mariadb::statement_ref query(mariadb::connection_ref connection, const std::string& sql, Args&&... args);
295 
296  /**
297  * The next parameter to be added is split off from the parameter pack.
298  *
299  * @param stmt The statement that will have parameterized values set on it.
300  * @param i The index of the current parameterized value.
301  * @param arg The next parameter to be added.
302  * @param args The remaining parameters to be added.
303  */
304  template<typename Arg, typename... Args>
305  void prepare(mariadb::statement_ref stmt, int i, Arg arg, Args&&... args);
306 
307  /**
308  * Specializations for each type of value to be parameterized.
309  * There are other parameter setters than those currently implemented, but so far there hasn't been a reason to add them.
310  *
311  * @param stmt The statement that will have parameterized values set on it.
312  * @param i The index of the current parameterized value.
313  * @param arg The next parameter to be added.
314  * @return The index of the next parameter to add.
315  */
316  template<typename Arg>
317  int prepare(mariadb::statement_ref stmt, int i, Arg arg);
318 
319  /**
320  * Nothing left to parameterize, so break out of the recursion.
321  */
322  void prepare(mariadb::statement_ref stmt, int i);
323 };
std::string db_tournament_query_
The text of the SQL query to use to retrieve any currently active tournaments.
Definition: dbconn.hpp:201
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.
void insert_addon_info(const std::string &instance_version, const std::string &id, const std::string &name, const std::string &type, const std::string &version, bool forum_auth, int topic_id)
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:193
void update_logout(unsigned long long login_id)
bool topic_id_exists(int topic_id)
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:189
std::string db_topics_table_
The name of the table that contains phpbb forum thread information.
Definition: dbconn.hpp:203
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
std::string db_addon_info_table_
The name of the table that contains add-on information.
Definition: dbconn.hpp:205
dbconn(const config &c)
Initializes the synchronous query connection as well as the account object that has the connection se...
std::string db_connection_history_table_
The name of the table that contains user connection history.
Definition: dbconn.hpp:207
mariadb::connection_ref connection_
The actual connection to the database.
Definition: dbconn.hpp:184
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:182
long get_single_long(mariadb::connection_ref connection, const std::string &sql, Args &&... args)
unsigned long long modify(mariadb::connection_ref connection, const std::string &sql, Args &&... args)
Executes non-select statements (ie: insert, update, delete).
bool is_user_in_group(const std::string &name, int group_id)
void get_users_for_ip(const std::string &ip, std::ostringstream *out)
std::string db_game_player_info_table_
The name of the table that contains player-level information per game.
Definition: dbconn.hpp:195
std::string db_game_content_info_table_
The name of the table that contains game content information.
Definition: dbconn.hpp:197
std::string get_uuid()
std::size_t i
Definition: function.cpp:940
void set_oos_flag(const std::string &uuid, int game_id)
bool user_exists(const std::string &name)
void get_ips_for_user(const std::string &username, std::ostringstream *out)
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:199
long get_forum_id(const std::string &name)
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:187
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
unsigned long long insert_login(const std::string &username, const std::string &ip, const std::string &version)
std::string db_extra_table_
The name of the table that contains additional user information.
Definition: dbconn.hpp:191
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)