The Battle for Wesnoth  1.19.7+dev
dbconn.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2020 - 2024
3  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
15 #pragma once
16 
17 #include "config.hpp"
21 
22 #include <mysql/mysql.h>
23 #include "mariadb++/account.hpp"
24 #include "mariadb++/connection.hpp"
25 #include "mariadb++/statement.hpp"
26 #include "mariadb++/result_set.hpp"
27 #include "mariadb++/exceptions.hpp"
28 
29 #include <vector>
30 #include <unordered_map>
31 
32 typedef std::vector<std::variant<bool, int, long, unsigned long long, std::string, const char*>> sql_parameters;
33 
34 /**
35  * This class is responsible for handling the database connections as well as executing queries and handling any results.
36  * @note The account and connection should never ever be provided to anything outside of this class.
37  * @note !DO NOT APPEND VALUES DIRECTLY TO THE SQL TEXT IN ANY QUERY!
38  */
39 class dbconn
40 {
41 public:
42  /**
43  * Initializes the synchronous query connection as well as the account object that has the connection settings.
44  *
45  * @param c The config object to read information from.
46  */
47  dbconn(const config& c);
48 
49  /**
50  * @see forum_user_handler::async_test_query().
51  */
52  int async_test_query(int limit);
53 
54  /**
55  * @see forum_user_handler::get_uuid().
56  */
57  std::string get_uuid();
58 
59  /**
60  * @see forum_user_handler::get_tournaments().
61  */
62  std::string get_tournaments();
63 
64  /**
65  * This is an asynchronous query that is executed on a separate connection to retrieve the game history for the
66  * provided player.
67  *
68  * @param player_id The forum ID of the player to get the game history for.
69  * @param offset The offset to provide to the database for where to start returning rows from.
70  * @param search_game_name Query for games matching this name. Supports leading and/or trailing wildcards.
71  * @param search_content_type The content type to query for (ie: scenario)
72  * @param search_content Query for games using this content ID. Supports leading and/or trailing wildcards.
73  * @return The simple_wml document containing the query results, or simply the @a error attribute if an exception is
74  * thrown.
75  */
76  std::unique_ptr<simple_wml::document> get_game_history(
77  int player_id, int offset, std::string search_game_name, int search_content_type, std::string search_content);
78 
79  /**
80  * @see forum_user_handler::user_exists().
81  */
82  bool user_exists(const std::string& name);
83 
84  /**
85  * @see forum_user_handler::get_forum_id().
86  */
87  long get_forum_id(const std::string& name);
88 
89  /**
90  * @param name The player's username.
91  * @return Whether the player has a row in the extra table.
92  */
93  bool extra_row_exists(const std::string& name);
94 
95  /**
96  * @param name The player's username.
97  * @param group_id The forum group ID to check if the user is part of.
98  * @return Whether the user is a member of the forum group.
99  */
100  bool is_user_in_group(const std::string& name, int group_id);
101 
102  /**
103  * @param table The table that will be queried.
104  * @param column The column that will be selected.
105  * @param name The player's username.
106  * @return The string value in the provided table and column for the provided username.
107  */
108  std::string get_user_string(const std::string& table, const std::string& column, const std::string& name);
109 
110  /**
111  * @param table The table that will be queried.
112  * @param column The column that will be selected.
113  * @param name The player's username.
114  * @return The int value in the provided table and column for the provided username.
115  */
116  int get_user_int(const std::string& table, const std::string& column, const std::string& name);
117 
118  /**
119  * The provided value is updated if a row exists or a new row inserted otherwise.
120  *
121  * @param column The column that the value will be put into.
122  * @param name The player's username.
123  * @param value The value to be put into the column.
124  */
125  void write_user_int(const std::string& column, const std::string& name, int value);
126 
127  /**
128  * @see forum_user_handler::user_is_banned().
129  */
130  ban_check get_ban_info(const std::string& name, const std::string& ip);
131 
132  /**
133  * @see forum_user_handler::db_insert_game_info().
134  */
136  const std::string& uuid,
137  int game_id,
138  const std::string& version,
139  const std::string& name,
140  int reload,
141  int observers,
142  int is_public,
143  int has_password);
144 
145  /**
146  * @see forum_user_handler::db_update_game_end().
147  */
148  void update_game_end(const std::string& uuid, int game_id, const std::string& replay_location);
149 
150  /**
151  * @see forum_user_handler::db_insert_game_player_info().
152  */
154  const std::string& uuid,
155  int game_id,
156  const std::string& username,
157  int side_number,
158  int is_host,
159  const std::string& faction,
160  const std::string& version,
161  const std::string& source,
162  const std::string& current_user,
163  const std::string& leaders);
164 
165  /**
166  * @see forum_user_handler::db_insert_game_content_info().
167  */
168  unsigned long long insert_game_content_info(
169  const std::string& uuid,
170  int game_id,
171  const std::string& type,
172  const std::string& name,
173  const std::string& id,
174  const std::string& addon_id,
175  const std::string& addon_version);
176 
177  /**
178  * @see forum_user_handler::db_set_oos_flag().
179  */
180  void set_oos_flag(const std::string& uuid, int game_id);
181 
182  /**
183  * @see forum_user_handler::db_topic_id_exists().
184  */
185  bool topic_id_exists(int topic_id);
186 
187  /**
188  * @see forum_user_handler::db_insert_addon_info().
189  */
191  const std::string& instance_version,
192  const std::string& id,
193  const std::string& name,
194  const std::string& type,
195  const std::string& version,
196  bool forum_auth,
197  int topic_id,
198  const std::string& uploader);
199 
200  /**
201  * @see forum_user_handler::db_insert_login().
202  */
203  unsigned long long insert_login(const std::string& username, const std::string& ip, const std::string& version);
204 
205  /**
206  * @see forum_user_handler::db_update_logout().
207  */
208  void update_logout(unsigned long long login_id);
209 
210  /**
211  * @see forum_user_handler::get_users_for_ip().
212  */
213  void get_users_for_ip(const std::string& ip, std::ostringstream* out);
214 
215  /**
216  * @see forum_user_handler::get_ips_for_users().
217  */
218  void get_ips_for_user(const std::string& username, std::ostringstream* out);
219 
220  /**
221  * @see forum_user_handler::db_update_addon_download_count().
222  */
224  const std::string& instance_version, const std::string& id, const std::string& version);
225 
226  /**
227  * @see forum_user_handler::is_user_primary_author().
228  * @see forum_user_handler::is_user_secondary_author().
229  */
231  const std::string& instance_version, const std::string& id, const std::string& username, int is_primary);
232 
233  /**
234  * @see forum_user_handler::db_delete_addon_authors().
235  */
236  void delete_addon_authors(const std::string& instance_version, const std::string& id);
237 
238  /**
239  * @see forum_user_handler::db_insert_addon_authors().
240  */
242  const std::string& instance_version, const std::string& id, const std::string& author, int is_primary);
243 
244  /**
245  * @see forum_user_handler::do_any_authors_exist().
246  */
247  bool do_any_authors_exist(const std::string& instance_version, const std::string& id);
248 
249 private:
250  /**
251  * The account used to connect to the database.
252  * Also contains the connection settings.
253  * @note settings put on the connection, rather than the account, are NOT kept if a reconnect occurs!
254  */
255  mariadb::account_ref account_;
256  /** The actual connection to the database. */
257  mariadb::connection_ref connection_;
258 
259  /** The name of the table that contains forum user information. */
260  std::string db_users_table_;
261  /** The name of the table that contains forum ban information. */
262  std::string db_banlist_table_;
263  /** The name of the table that contains additional user information. */
264  std::string db_extra_table_;
265  /** The name of the table that contains game-level information. */
266  std::string db_game_info_table_;
267  /** The name of the table that contains player-level information per game. */
269  /** The name of the table that contains game content information. */
271  /** The name of the table that contains forum group information. */
272  std::string db_user_group_table_;
273  /** The text of the SQL query to use to retrieve any currently active tournaments. */
274  std::string db_tournament_query_;
275  /** The name of the table that contains phpbb forum thread information */
276  std::string db_topics_table_;
277  /** The name of the table that contains add-on information. */
278  std::string db_addon_info_table_;
279  /** The name of the table that contains user connection history. */
281  /** The name of the table that contains the add-on authors information */
283 
284  /**
285  * This is used to write out error text when an SQL-related exception occurs.
286  *
287  * @param text Some custom text to log.
288  * @param e The exception that occurred which has information about what went wrong.
289  */
290  void log_sql_exception(const std::string& text, const mariadb::exception::base& e);
291 
292  /**
293  * Creates a new connection object from the account.
294  */
295  mariadb::connection_ref create_connection();
296 
297  /**
298  * Queries can return data with various types that can't be easily fit into a pre-determined structure.
299  * Therefore for queries that can return multiple rows with multiple columns, a class that extends @ref rs_base
300  * handles reading the results.
301  *
302  * @param connection The database connection that will be used to execute the query.
303  * @param base The class that will handle reading the results.
304  * @param sql The SQL text to be executed.
305  * @param params The parameterized values to be inserted into the query.
306  */
308  const mariadb::connection_ref& connection, rs_base& base, const std::string& sql, const sql_parameters& params);
309 
310  /**
311  * @param connection The database connection that will be used to execute the query.
312  * @param sql The SQL text to be executed.
313  * @param params The parameterized values to be inserted into the query.
314  * @return The single string value queried.
315  * @throws mariadb::exception::base when the query finds no value to be retrieved.
316  */
317  std::string get_single_string(
318  const mariadb::connection_ref& connection, const std::string& sql, const sql_parameters& params);
319 
320  /**
321  * @param connection The database connection that will be used to execute the query.
322  * @param sql The SQL text to be executed.
323  * @param params The parameterized values to be inserted into the query.
324  * @return The single long value queried.
325  * @throws mariadb::exception::base when the query finds no value to be retrieved.
326  */
327  long get_single_long(const mariadb::connection_ref& connection, const std::string& sql, const sql_parameters& params);
328 
329  /**
330  * @param connection The database connection that will be used to execute the query.
331  * @param sql The SQL text to be executed.
332  * @param params The parameterized values to be inserted into the query.
333  * @return True if any data was returned by the query, otherwise false.
334  */
335  bool exists(const mariadb::connection_ref& connection, const std::string& sql, const sql_parameters& params);
336 
337  /**
338  * Executes a select statement.
339  *
340  * @param connection The database connection that will be used to execute the query.
341  * @param sql The SQL text to be executed.
342  * @param params The parameterized values to be inserted into the query.
343  * @return A result set containing the results of the select statement executed.
344  */
345  mariadb::result_set_ref select(
346  const mariadb::connection_ref& connection, const std::string& sql, const sql_parameters& params);
347 
348  /**
349  * Executes non-select statements (ie: insert, update, delete).
350  *
351  * @param connection The database connection that will be used to execute the query.
352  * @param sql The SQL text to be executed.
353  * @param params The parameterized values to be inserted into the query.
354  * @return The number of rows modified.
355  */
356  unsigned long long modify(const mariadb::connection_ref& connection, const std::string& sql, const sql_parameters& params);
357 
358  /**
359  * Executes non-select statements (ie: insert, update, delete), but primarily intended for inserts that return a
360  * generated ID.
361  *
362  * @param connection The database connection that will be used to execute the query.
363  * @param sql The SQL text to be executed.
364  * @param params The parameterized values to be inserted into the query.
365  * @return The value of an AUTO_INCREMENT column on the table being modified.
366  */
367  unsigned long long modify_get_id(
368  const mariadb::connection_ref& connection, const std::string& sql, const sql_parameters& params);
369 
370  /**
371  * For a given connection, set the provided SQL and parameters on a statement.
372  *
373  * @param connection The database connection that will be used to execute the query.
374  * @param sql The SQL text to be executed.
375  * @param params The parameterized values to be inserted into the query.
376  * @return A statement ready to be executed.
377  */
378  mariadb::statement_ref query(
379  const mariadb::connection_ref& connection, const std::string& sql, const sql_parameters& params);
380 };
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:172
This class is responsible for handling the database connections as well as executing queries and hand...
Definition: dbconn.hpp:40
void delete_addon_authors(const std::string &instance_version, const std::string &id)
void insert_addon_author(const std::string &instance_version, const std::string &id, const std::string &author, int is_primary)
bool do_any_authors_exist(const std::string &instance_version, const std::string &id)
void update_addon_download_count(const std::string &instance_version, const std::string &id, const std::string &version)
std::string db_tournament_query_
The text of the SQL query to use to retrieve any currently active tournaments.
Definition: dbconn.hpp:274
bool topic_id_exists(int topic_id)
int async_test_query(int limit)
bool is_user_author(const std::string &instance_version, const std::string &id, const std::string &username, int is_primary)
mariadb::connection_ref connection_
The actual connection to the database.
Definition: dbconn.hpp:257
bool exists(const mariadb::connection_ref &connection, const std::string &sql, const sql_parameters &params)
long get_forum_id(const std::string &name)
std::unique_ptr< simple_wml::document > get_game_history(int player_id, int offset, std::string search_game_name, int search_content_type, std::string search_content)
This is an asynchronous query that is executed on a separate connection to retrieve the game history ...
void get_ips_for_user(const std::string &username, std::ostringstream *out)
bool is_user_in_group(const std::string &name, int group_id)
std::string db_addon_authors_table_
The name of the table that contains the add-on authors information.
Definition: dbconn.hpp:282
bool user_exists(const std::string &name)
void get_users_for_ip(const std::string &ip, std::ostringstream *out)
long get_single_long(const mariadb::connection_ref &connection, const std::string &sql, const sql_parameters &params)
std::string get_single_string(const mariadb::connection_ref &connection, const std::string &sql, const sql_parameters &params)
std::string db_banlist_table_
The name of the table that contains forum ban information.
Definition: dbconn.hpp:262
unsigned long long insert_login(const std::string &username, const std::string &ip, const std::string &version)
mariadb::connection_ref create_connection()
Creates a new connection object from the account.
std::string db_extra_table_
The name of the table that contains additional user information.
Definition: dbconn.hpp:264
void update_logout(unsigned long long login_id)
std::string db_addon_info_table_
The name of the table that contains add-on information.
Definition: dbconn.hpp:278
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.
std::string db_game_content_info_table_
The name of the table that contains game content information.
Definition: dbconn.hpp:270
bool extra_row_exists(const std::string &name)
void get_complex_results(const mariadb::connection_ref &connection, rs_base &base, const std::string &sql, const sql_parameters &params)
Queries can return data with various types that can't be easily fit into a pre-determined structure.
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_user_group_table_
The name of the table that contains forum group information.
Definition: dbconn.hpp:272
mariadb::account_ref account_
The account used to connect to the database.
Definition: dbconn.hpp:255
void set_oos_flag(const std::string &uuid, int game_id)
void update_game_end(const std::string &uuid, int game_id, const std::string &replay_location)
std::string db_game_info_table_
The name of the table that contains game-level information.
Definition: dbconn.hpp:266
std::string db_game_player_info_table_
The name of the table that contains player-level information per game.
Definition: dbconn.hpp:268
mariadb::statement_ref query(const mariadb::connection_ref &connection, const std::string &sql, const sql_parameters &params)
For a given connection, set the provided SQL and parameters on a statement.
std::string db_connection_history_table_
The name of the table that contains user connection history.
Definition: dbconn.hpp:280
int get_user_int(const std::string &table, const std::string &column, const std::string &name)
unsigned long long modify(const mariadb::connection_ref &connection, const std::string &sql, const sql_parameters &params)
Executes non-select statements (ie: insert, update, delete).
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, const std::string &uploader)
ban_check get_ban_info(const std::string &name, const std::string &ip)
unsigned long long modify_get_id(const mariadb::connection_ref &connection, const std::string &sql, const sql_parameters &params)
Executes non-select statements (ie: insert, update, delete), but primarily intended for inserts that ...
std::string db_topics_table_
The name of the table that contains phpbb forum thread information.
Definition: dbconn.hpp:276
std::string get_user_string(const std::string &table, const std::string &column, const std::string &name)
std::string db_users_table_
The name of the table that contains forum user information.
Definition: dbconn.hpp:260
dbconn(const config &c)
Initializes the synchronous query connection as well as the account object that has the connection se...
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)
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, const std::string &leaders)
mariadb::result_set_ref select(const mariadb::connection_ref &connection, const std::string &sql, const sql_parameters &params)
Executes a select statement.
std::string get_uuid()
std::string get_tournaments()
unsigned long long 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 &addon_id, const std::string &addon_version)
Definitions for the interface to Wesnoth Markup Language (WML).
std::vector< std::variant< bool, int, long, unsigned long long, std::string, const char * > > sql_parameters
Definition: dbconn.hpp:32
int side_number
Definition: game_info.hpp:40
mock_char c
#define e