The Battle for Wesnoth  1.19.5+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  */
135  void insert_game_info(const std::string& uuid,
136  int game_id,
137  const std::string& version,
138  const std::string& name,
139  int reload,
140  int observers,
141  int is_public,
142  int has_password);
143 
144  /**
145  * @see forum_user_handler::db_update_game_end().
146  */
147  void update_game_end(const std::string& uuid, int game_id, const std::string& replay_location);
148 
149  /**
150  * @see forum_user_handler::db_insert_game_player_info().
151  */
152  void insert_game_player_info(const std::string& uuid,
153  int game_id,
154  const std::string& username,
155  int side_number,
156  int is_host,
157  const std::string& faction,
158  const std::string& version,
159  const std::string& source,
160  const std::string& current_user,
161  const std::string& leaders);
162 
163  /**
164  * @see forum_user_handler::db_insert_game_content_info().
165  */
166  unsigned long long insert_game_content_info(const std::string& uuid,
167  int game_id,
168  const std::string& type,
169  const std::string& name,
170  const std::string& id,
171  const std::string& addon_id,
172  const std::string& addon_version);
173 
174  /**
175  * @see forum_user_handler::db_set_oos_flag().
176  */
177  void set_oos_flag(const std::string& uuid, int game_id);
178 
179  /**
180  * @see forum_user_handler::db_topic_id_exists().
181  */
182  bool topic_id_exists(int topic_id);
183 
184  /**
185  * @see forum_user_handler::db_insert_addon_info().
186  */
187  void insert_addon_info(const std::string& instance_version,
188  const std::string& id,
189  const std::string& name,
190  const std::string& type,
191  const std::string& version,
192  bool forum_auth,
193  int topic_id,
194  const std::string uploader);
195 
196  /**
197  * @see forum_user_handler::db_insert_login().
198  */
199  unsigned long long insert_login(const std::string& username, const std::string& ip, const std::string& version);
200 
201  /**
202  * @see forum_user_handler::db_update_logout().
203  */
204  void update_logout(unsigned long long login_id);
205 
206  /**
207  * @see forum_user_handler::get_users_for_ip().
208  */
209  void get_users_for_ip(const std::string& ip, std::ostringstream* out);
210 
211  /**
212  * @see forum_user_handler::get_ips_for_users().
213  */
214  void get_ips_for_user(const std::string& username, std::ostringstream* out);
215 
216  /**
217  * @see forum_user_handler::db_update_addon_download_count().
218  */
220  const std::string& instance_version, const std::string& id, const std::string& version);
221 
222  /**
223  * @see forum_user_handler::is_user_primary_author().
224  * @see forum_user_handler::is_user_secondary_author().
225  */
227  const std::string& instance_version, const std::string& id, const std::string& username, int is_primary);
228 
229  /**
230  * @see forum_user_handler::db_delete_addon_authors().
231  */
232  void delete_addon_authors(const std::string& instance_version, const std::string& id);
233 
234  /**
235  * @see forum_user_handler::db_insert_addon_authors().
236  */
238  const std::string& instance_version, const std::string& id, const std::string author, int is_primary);
239 
240  /**
241  * @see forum_user_handler::do_any_authors_exist().
242  */
243  bool do_any_authors_exist(const std::string& instance_version, const std::string& id);
244 
245 private:
246  /**
247  * The account used to connect to the database.
248  * Also contains the connection settings.
249  * @note settings put on the connection, rather than the account, are NOT kept if a reconnect occurs!
250  */
251  mariadb::account_ref account_;
252  /** The actual connection to the database. */
253  mariadb::connection_ref connection_;
254 
255  /** The name of the table that contains forum user information. */
256  std::string db_users_table_;
257  /** The name of the table that contains forum ban information. */
258  std::string db_banlist_table_;
259  /** The name of the table that contains additional user information. */
260  std::string db_extra_table_;
261  /** The name of the table that contains game-level information. */
262  std::string db_game_info_table_;
263  /** The name of the table that contains player-level information per game. */
265  /** The name of the table that contains game content information. */
267  /** The name of the table that contains forum group information. */
268  std::string db_user_group_table_;
269  /** The text of the SQL query to use to retrieve any currently active tournaments. */
270  std::string db_tournament_query_;
271  /** The name of the table that contains phpbb forum thread information */
272  std::string db_topics_table_;
273  /** The name of the table that contains add-on information. */
274  std::string db_addon_info_table_;
275  /** The name of the table that contains user connection history. */
277  /** The name of the table that contains the add-on authors information */
279 
280  /**
281  * This is used to write out error text when an SQL-related exception occurs.
282  *
283  * @param text Some custom text to log.
284  * @param e The exception that occurred which has information about what went wrong.
285  */
286  void log_sql_exception(const std::string& text, const mariadb::exception::base& e);
287 
288  /**
289  * Creates a new connection object from the account.
290  */
291  mariadb::connection_ref create_connection();
292 
293  /**
294  * Queries can return data with various types that can't be easily fit into a pre-determined structure.
295  * Therefore for queries that can return multiple rows with multiple columns, a class that extends @ref rs_base
296  * handles reading the results.
297  *
298  * @param connection The database connection that will be used to execute the query.
299  * @param base The class that will handle reading the results.
300  * @param sql The SQL text to be executed.
301  * @param params The parameterized values to be inserted into the query.
302  */
304  mariadb::connection_ref connection, rs_base& base, const std::string& sql, const sql_parameters& params);
305 
306  /**
307  * @param connection The database connection that will be used to execute the query.
308  * @param sql The SQL text to be executed.
309  * @param params The parameterized values to be inserted into the query.
310  * @return The single string value queried.
311  * @throws mariadb::exception::base when the query finds no value to be retrieved.
312  */
313  std::string get_single_string(
314  mariadb::connection_ref connection, const std::string& sql, const sql_parameters& params);
315 
316  /**
317  * @param connection The database connection that will be used to execute the query.
318  * @param sql The SQL text to be executed.
319  * @param params The parameterized values to be inserted into the query.
320  * @return The single long value queried.
321  * @throws mariadb::exception::base when the query finds no value to be retrieved.
322  */
323  long get_single_long(mariadb::connection_ref connection, const std::string& sql, const sql_parameters& params);
324 
325  /**
326  * @param connection The database connection that will be used to execute the query.
327  * @param sql The SQL text to be executed.
328  * @param params The parameterized values to be inserted into the query.
329  * @return True if any data was returned by the query, otherwise false.
330  */
331  bool exists(mariadb::connection_ref connection, const std::string& sql, const sql_parameters& params);
332 
333  /**
334  * Executes a select statement.
335  *
336  * @param connection The database connection that will be used to execute the query.
337  * @param sql The SQL text to be executed.
338  * @param params The parameterized values to be inserted into the query.
339  * @return A result set containing the results of the select statement executed.
340  */
341  mariadb::result_set_ref select(
342  mariadb::connection_ref connection, const std::string& sql, const sql_parameters& params);
343 
344  /**
345  * Executes non-select statements (ie: insert, update, delete).
346  *
347  * @param connection The database connection that will be used to execute the query.
348  * @param sql The SQL text to be executed.
349  * @param params The parameterized values to be inserted into the query.
350  * @return The number of rows modified.
351  */
352  unsigned long long modify(mariadb::connection_ref connection, const std::string& sql, const sql_parameters& params);
353 
354  /**
355  * Executes non-select statements (ie: insert, update, delete), but primarily intended for inserts that return a
356  * generated ID.
357  *
358  * @param connection The database connection that will be used to execute the query.
359  * @param sql The SQL text to be executed.
360  * @param params The parameterized values to be inserted into the query.
361  * @return The value of an AUTO_INCREMENT column on the table being modified.
362  */
363  unsigned long long modify_get_id(
364  mariadb::connection_ref connection, const std::string& sql, const sql_parameters& params);
365 
366  /**
367  * For a given connection, set the provided SQL and parameters on a statement.
368  *
369  * @param connection The database connection that will be used to execute the query.
370  * @param sql The SQL text to be executed.
371  * @param params The parameterized values to be inserted into the query.
372  * @return A statement ready to be executed.
373  */
374  mariadb::statement_ref query(
375  mariadb::connection_ref connection, const std::string& sql, const sql_parameters& params);
376 };
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)
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)
mariadb::statement_ref query(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_tournament_query_
The text of the SQL query to use to retrieve any currently active tournaments.
Definition: dbconn.hpp:270
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:253
long get_forum_id(const std::string &name)
long get_single_long(mariadb::connection_ref connection, const std::string &sql, const sql_parameters &params)
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 ...
unsigned long long modify(mariadb::connection_ref connection, const std::string &sql, const sql_parameters &params)
Executes non-select statements (ie: insert, update, delete).
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:278
bool user_exists(const std::string &name)
void get_users_for_ip(const std::string &ip, std::ostringstream *out)
mariadb::result_set_ref select(mariadb::connection_ref connection, const std::string &sql, const sql_parameters &params)
Executes a select statement.
void insert_addon_author(const std::string &instance_version, const std::string &id, const std::string author, int is_primary)
std::string get_single_string(mariadb::connection_ref connection, const std::string &sql, const sql_parameters &params)
unsigned long long modify_get_id(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_banlist_table_
The name of the table that contains forum ban information.
Definition: dbconn.hpp:258
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:260
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:274
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.
bool exists(mariadb::connection_ref connection, const std::string &sql, const sql_parameters &params)
std::string db_game_content_info_table_
The name of the table that contains game content information.
Definition: dbconn.hpp:266
bool extra_row_exists(const std::string &name)
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:268
void get_complex_results(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.
mariadb::account_ref account_
The account used to connect to the database.
Definition: dbconn.hpp:251
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:262
std::string db_game_player_info_table_
The name of the table that contains player-level information per game.
Definition: dbconn.hpp:264
std::string db_connection_history_table_
The name of the table that contains user connection history.
Definition: dbconn.hpp:276
int get_user_int(const std::string &table, const std::string &column, const std::string &name)
ban_check get_ban_info(const std::string &name, const std::string &ip)
std::string db_topics_table_
The name of the table that contains phpbb forum thread information.
Definition: dbconn.hpp:272
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)
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:256
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)
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