26 #define ERR_SQL LOG_STREAM(err, log_sql_handler) 27 #define WRN_SQL LOG_STREAM(warn, log_sql_handler) 28 #define LOG_SQL LOG_STREAM(info, log_sql_handler) 29 #define DBG_SQL LOG_STREAM(debug, log_sql_handler) 32 : db_users_table_(c[
"db_users_table"].str())
33 , db_banlist_table_(c[
"db_banlist_table"].str())
34 , db_extra_table_(c[
"db_extra_table"].str())
35 , db_game_info_table_(c[
"db_game_info_table"].str())
36 , db_game_player_info_table_(c[
"db_game_player_info_table"].str())
37 , db_game_content_info_table_(c[
"db_game_content_info_table"].str())
38 , db_user_group_table_(c[
"db_user_group_table"].str())
39 , db_tournament_query_(c[
"db_tournament_query"].str())
40 , db_topics_table_(c[
"db_topics_table"].str())
41 , db_addon_info_table_(c[
"db_addon_info_table"].str())
42 , db_connection_history_table_(c[
"db_connection_history_table"].str())
43 , db_addon_authors_table_(c[
"db_addon_authors_table"].str())
47 account_ = mariadb::account::create(c[
"db_host"].str(), c[
"db_user"].str(), c[
"db_password"].str());
48 account_->set_connect_option(mysql_option::MYSQL_SET_CHARSET_NAME, std::string(
"utf8mb4"));
49 account_->set_schema(c[
"db_name"].str());
51 connection_ = create_connection();
53 catch(
const mariadb::exception::base&
e)
55 log_sql_exception(
"Failed to connect to the database!", e);
61 ERR_SQL << text <<
'\n' 62 <<
"what: " << e.what() <<
'\n' 63 <<
"error id: " << e.error_id();
68 return mariadb::connection::create(account_);
76 std::string sql =
"with recursive TEST(T) as " 80 "select T+1 from TEST where T < ? " 82 "select count(*) from TEST";
83 int t = get_single_long(create_connection(), sql, limit);
91 return get_single_string(connection_,
"SELECT UUID()");
93 catch(
const mariadb::exception::base& e)
95 log_sql_exception(
"Could not retrieve a UUID!", e);
102 if(db_tournament_query_ ==
"")
110 get_complex_results(connection_, t, db_tournament_query_);
113 catch(
const mariadb::exception::base& e)
115 log_sql_exception(
"Could not retrieve the tournaments!", e);
124 std::string game_history_query =
"select " 128 " GROUP_CONCAT(CONCAT(player.USER_NAME, ':', player.FACTION)) as PLAYERS, " 129 " IFNULL(scenario.NAME, '') as SCENARIO_NAME, " 130 " IFNULL(scenario.ID, '') as SCENARIO_ID, " 131 " IFNULL(era.NAME, '') as ERA_NAME, " 132 " IFNULL(era.ID, '') as ERA_ID, " 133 " IFNULL(GROUP_CONCAT(distinct mods.NAME, '') as MODIFICATION_NAMES, " 134 " IFNULL(GROUP_CONCAT(distinct mods.ID), '') as MODIFICATION_IDS, " 136 " when game.PUBLIC = 1 " 137 " then concat('https://replays.wesnoth.org/', substring(game.INSTANCE_VERSION, 1, 4), '/', year(game.END_TIME), '/', lpad(month(game.END_TIME), 2, '0'), '/', lpad(day(game.END_TIME), 2, '0'), '/', game.REPLAY_NAME) " 139 " end as REPLAY_URL " 140 "from "+db_game_info_table_+
" game " 141 "inner join "+db_game_player_info_table_+
" player " 145 " from "+db_game_player_info_table_+
" player1 " 146 " where game.INSTANCE_UUID = player1.INSTANCE_UUID " 147 " and game.GAME_ID = player1.GAME_ID " 148 " and player1.USER_ID = ? " 150 " and game.INSTANCE_UUID = player.INSTANCE_UUID " 151 " and game.GAME_ID = player.GAME_ID " 152 " and player.USER_ID != -1 " 153 " and game.END_TIME is not NULL " 154 "inner join "+db_game_content_info_table_+
" scenario " 155 " on scenario.TYPE = 'scenario' " 156 " and scenario.INSTANCE_UUID = game.INSTANCE_UUID " 157 " and scenario.GAME_ID = game.GAME_ID " 158 "inner join "+db_game_content_info_table_+
" era " 159 " on era.TYPE = 'era' " 160 " and era.INSTANCE_UUID = game.INSTANCE_UUID " 161 " and era.GAME_ID = game.GAME_ID " 162 "left join "+db_game_content_info_table_+
" mods " 163 " on mods.TYPE = 'modification' " 164 " and mods.INSTANCE_UUID = game.INSTANCE_UUID " 165 " and mods.GAME_ID = game.GAME_ID " 166 "group by game.INSTANCE_UUID, game.GAME_ID " 167 "order by game.START_TIME desc " 168 "limit 11 offset ? ";
171 get_complex_results(create_connection(), gh, game_history_query, player_id, offset);
174 catch(
const mariadb::exception::base& e)
176 log_sql_exception(
"Could not retrieve the game history for forum ID `"+std::to_string(player_id)+
"`!", e);
177 auto doc = std::make_unique<simple_wml::document>();
178 doc->set_attr(
"error",
"Error retrieving game history.");
187 return exists(connection_,
"SELECT 1 FROM `"+db_users_table_+
"` WHERE UPPER(username)=UPPER(?)", name);
189 catch(
const mariadb::exception::base& e)
191 log_sql_exception(
"Unable to check if user row for '"+name+
"' exists!", e);
200 return get_single_long(connection_,
"SELECT IFNULL((SELECT user_id FROM `"+db_users_table_+
"` WHERE UPPER(username)=UPPER(?)), 0)", name);
202 catch(
const mariadb::exception::base& e)
204 log_sql_exception(
"Unable to get user_id for '"+name+
"'!", e);
213 return exists(connection_,
"SELECT 1 FROM `"+db_extra_table_+
"` WHERE UPPER(username)=UPPER(?)", name);
215 catch(
const mariadb::exception::base& e)
217 log_sql_exception(
"Unable to check if extra row for '"+name+
"' exists!", e);
226 return exists(connection_,
"SELECT 1 FROM `"+db_users_table_+
"` u, `"+db_user_group_table_+
"` ug WHERE UPPER(u.username)=UPPER(?) AND u.USER_ID = ug.USER_ID AND ug.GROUP_ID = ?",
229 catch(
const mariadb::exception::base& e)
231 log_sql_exception(
"Unable to check if the user '"+name+
"' is in group '"+std::to_string(group_id)+
"'!", e);
242 get_complex_results(connection_, b,
"select ban_userid, ban_email, case when ban_ip != '' then 1 when ban_userid != 0 then 2 when ban_email != '' then 3 end as ban_type, ban_end from `"+db_banlist_table_+
"` where (ban_ip = ? or ban_userid = (select user_id from `"+db_users_table_+
"` where UPPER(username) = UPPER(?)) or UPPER(ban_email) = (select UPPER(user_email) from `"+db_users_table_+
"` where UPPER(username) = UPPER(?))) AND ban_exclude = 0 AND (ban_end = 0 OR ban_end >= ?)",
243 ip, name, name, std::time(
nullptr));
246 catch(
const mariadb::exception::base& e)
248 log_sql_exception(
"Failed to check ban info for user '"+name+
"' connecting from ip '"+ip+
"'!", e);
253 std::string
dbconn::get_user_string(
const std::string& table,
const std::string& column,
const std::string& name)
257 return get_single_string(connection_,
"SELECT `"+column+
"` from `"+table+
"` WHERE UPPER(username)=UPPER(?)", name);
259 catch(
const mariadb::exception::base& e)
261 log_sql_exception(
"Unable to query column `"+column+
"` from table `"+table+
"` for user `"+name+
"`", e);
265 int dbconn::get_user_int(
const std::string& table,
const std::string& column,
const std::string& name)
269 return static_cast<int>(get_single_long(connection_,
"SELECT `"+column+
"` from `"+table+
"` WHERE UPPER(username)=UPPER(?)", name));
271 catch(
const mariadb::exception::base& e)
273 log_sql_exception(
"Unable to query column `"+column+
"` from table `"+table+
"` for user `"+name+
"`", e);
281 if(!extra_row_exists(name))
283 modify(connection_,
"INSERT INTO `"+db_extra_table_+
"` VALUES(?,?,'0')", name, value);
285 modify(connection_,
"UPDATE `"+db_extra_table_+
"` SET "+column+
"=? WHERE UPPER(username)=UPPER(?)", value, name);
287 catch(
const mariadb::exception::base& e)
289 log_sql_exception(
"Unable to write `"+std::to_string(value)+
"` to column `"+column+
"` on table `"+db_extra_table_+
"` for user `"+name+
"`", e);
293 void dbconn::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)
297 modify(connection_,
"INSERT INTO `"+db_game_info_table_+
"`(INSTANCE_UUID, GAME_ID, INSTANCE_VERSION, GAME_NAME, RELOAD, OBSERVERS, PUBLIC, PASSWORD) VALUES(?, ?, ?, ?, ?, ?, ?, ?)",
298 uuid, game_id, version, name, reload, observers, is_public, has_password);
300 catch(
const mariadb::exception::base& e)
302 log_sql_exception(
"Failed to insert game info row for UUID `"+uuid+
"` and game ID `"+std::to_string(game_id)+
"`", e);
309 modify(connection_,
"UPDATE `"+db_game_info_table_+
"` SET END_TIME = CURRENT_TIMESTAMP, REPLAY_NAME = ? WHERE INSTANCE_UUID = ? AND GAME_ID = ?",
310 replay_location, uuid, game_id);
312 catch(
const mariadb::exception::base& e)
314 log_sql_exception(
"Failed to update the game end for game info row for UUID `"+uuid+
"` and game ID `"+std::to_string(game_id)+
"`", e);
317 void dbconn::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)
321 modify(connection_,
"INSERT INTO `"+db_game_player_info_table_+
"`(INSTANCE_UUID, GAME_ID, USER_ID, SIDE_NUMBER, IS_HOST, FACTION, CLIENT_VERSION, CLIENT_SOURCE, USER_NAME) VALUES(?, ?, IFNULL((SELECT user_id FROM `"+db_users_table_+
"` WHERE username = ?), -1), ?, ?, ?, ?, ?, ?)",
322 uuid, game_id, username, side_number, is_host, faction, version, source, current_user);
324 catch(
const mariadb::exception::base& e)
326 log_sql_exception(
"Failed to insert game player info row for UUID `"+uuid+
"` and game ID `"+std::to_string(game_id)+
"`", e);
329 unsigned long long dbconn::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)
333 return modify(connection_,
"INSERT INTO `"+db_game_content_info_table_+
"`(INSTANCE_UUID, GAME_ID, TYPE, NAME, ID, ADDON_ID, ADDON_VERSION) VALUES(?, ?, ?, ?, ?, ?, ?)",
334 uuid, game_id, type, name,
id, addon_id, addon_version);
336 catch(
const mariadb::exception::base& e)
338 log_sql_exception(
"Failed to insert game content info row for UUID `"+uuid+
"` and game ID `"+std::to_string(game_id)+
"`", e);
346 modify(connection_,
"UPDATE `"+db_game_info_table_+
"` SET OOS = 1 WHERE INSTANCE_UUID = ? AND GAME_ID = ?",
349 catch(
const mariadb::exception::base& e)
351 log_sql_exception(
"Failed to set the OOS flag for UUID `"+uuid+
"` and game ID `"+std::to_string(game_id)+
"`", e);
358 return exists(connection_,
"SELECT 1 FROM `"+db_topics_table_+
"` WHERE TOPIC_ID = ?",
361 catch(
const mariadb::exception::base& e)
363 log_sql_exception(
"Unable to check whether `"+std::to_string(topic_id)+
"` exists.", e);
368 void dbconn::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)
372 modify(connection_,
"INSERT INTO `"+db_addon_info_table_+
"`(INSTANCE_VERSION, ADDON_ID, ADDON_NAME, TYPE, VERSION, FORUM_AUTH, FEEDBACK_TOPIC, UPLOADER) VALUES(?, ?, ?, ?, ?, ?, ?, ?)",
373 instance_version,
id, name, type, version, forum_auth, topic_id, uploader);
375 catch(
const mariadb::exception::base& e)
377 log_sql_exception(
"Unable to insert add-on info for add-on `"+
id+
"` for instance `"+instance_version+
"`.", e);
381 unsigned long long dbconn::insert_login(
const std::string& username,
const std::string& ip,
const std::string& version)
385 return modify_get_id(connection_,
"INSERT INTO `"+db_connection_history_table_+
"`(USER_NAME, IP, VERSION) values(lower(?), ?, ?)",
386 username, ip, version);
388 catch(
const mariadb::exception::base& e)
390 log_sql_exception(
"Unable to insert login row user `"+username+
"` and ip `"+ip+
"`.", e);
399 modify(connection_,
"UPDATE `"+db_connection_history_table_+
"` SET LOGOUT_TIME = CURRENT_TIMESTAMP WHERE LOGIN_ID = ?",
402 catch(
const mariadb::exception::base& e)
404 log_sql_exception(
"Unable to update login row `"+std::to_string(login_id)+
"`.", e);
412 mariadb::result_set_ref rslt = select(connection_,
"SELECT USER_NAME, IP, date_format(LOGIN_TIME, '%Y/%m/%d %h:%i:%s'), coalesce(date_format(LOGOUT_TIME, '%Y/%m/%d %h:%i:%s'), '(not set)') FROM `"+db_connection_history_table_+
"` WHERE IP LIKE ? order by LOGIN_TIME",
415 *out <<
"\nCount of results for ip: " << rslt->row_count();
419 *out <<
"\nFound user " << rslt->get_string(0) <<
" with ip " << rslt->get_string(1)
420 <<
", logged in at " << rslt->get_string(2) <<
" and logged out at " << rslt->get_string(3);
423 catch(
const mariadb::exception::base& e)
425 log_sql_exception(
"Unable to select rows for ip `"+ip+
"`.", e);
433 mariadb::result_set_ref rslt = select(connection_,
"SELECT USER_NAME, IP, date_format(LOGIN_TIME, '%Y/%m/%d %h:%i:%s'), coalesce(date_format(LOGOUT_TIME, '%Y/%m/%d %h:%i:%s'), '(not set)') FROM `"+db_connection_history_table_+
"` WHERE USER_NAME LIKE ? order by LOGIN_TIME",
436 *out <<
"\nCount of results for user: " << rslt->row_count();
440 *out <<
"\nFound user " << rslt->get_string(0) <<
" with ip " << rslt->get_string(1)
441 <<
", logged in at " << rslt->get_string(2) <<
" and logged out at " << rslt->get_string(3);
444 catch(
const mariadb::exception::base& e)
446 log_sql_exception(
"Unable to select rows for player `"+username+
"`.", e);
454 modify(connection_,
"UPDATE `"+db_addon_info_table_+
"` SET DOWNLOAD_COUNT = DOWNLOAD_COUNT+1 WHERE INSTANCE_VERSION = ? AND ADDON_ID = ? AND VERSION = ?",
455 instance_version,
id, version);
457 catch(
const mariadb::exception::base& e)
459 log_sql_exception(
"Unable to update download count for add-on "+
id+
" with version "+version+
".", e);
463 bool dbconn::is_user_author(
const std::string& instance_version,
const std::string&
id,
const std::string& username,
int is_primary) {
466 return exists(connection_,
"SELECT 1 FROM `"+db_addon_authors_table_+
"` WHERE INSTANCE_VERSION = ? AND ADDON_ID = ? AND AUTHOR = ? AND IS_PRIMARY = ?",
467 instance_version,
id, username, is_primary);
469 catch(
const mariadb::exception::base& e)
471 log_sql_exception(
"Unable to check whether `"+username+
"` is an author of "+
id+
" for version "+instance_version+
".", e);
479 modify(connection_,
"DELETE FROM `"+db_addon_authors_table_+
"` WHERE INSTANCE_VERSION = ? AND ADDON_ID = ?",
480 instance_version,
id);
482 catch(
const mariadb::exception::base& e)
484 log_sql_exception(
"Unable to delete addon authors for "+
id+
" and version "+instance_version+
".", e);
488 void dbconn::insert_addon_author(
const std::string& instance_version,
const std::string&
id,
const std::string author,
int is_primary) {
491 modify(connection_,
"INSERT INTO `"+db_addon_authors_table_+
"`(INSTANCE_VERSION, ADDON_ID, AUTHOR, IS_PRIMARY) VALUES(?,?,?,?)",
492 instance_version,
id, author, is_primary);
494 catch(
const mariadb::exception::base& e)
496 log_sql_exception(
"Unable to delete addon authors for "+
id+
" and version "+instance_version+
".", e);
503 return exists(connection_,
"SELECT 1 FROM `"+db_addon_authors_table_+
"` WHERE INSTANCE_VERSION = ? AND ADDON_ID = ?",
504 instance_version,
id);
506 catch(
const mariadb::exception::base& e)
508 log_sql_exception(
"Unable to check whether authors exist for "+
id+
" for version "+instance_version+
".", e);
516 template<
typename... Args>
519 mariadb::result_set_ref rslt = select(connection, sql, args...);
525 template<
typename... Args>
528 mariadb::result_set_ref rslt = select(connection, sql, args...);
531 return rslt->get_string(0);
535 throw mariadb::exception::base(
"No string value found in the database!");
538 template<
typename... Args>
541 mariadb::result_set_ref rslt = select(connection, sql, args...);
547 switch(rslt->column_type(0))
549 case mariadb::value::type::decimal:
550 return static_cast<long>(rslt->get_decimal(0).float32());
551 case mariadb::value::type::unsigned8:
552 case mariadb::value::type::signed8:
553 return rslt->get_signed8(0);
554 case mariadb::value::type::unsigned16:
555 case mariadb::value::type::signed16:
556 return rslt->get_signed16(0);
557 case mariadb::value::type::unsigned32:
558 case mariadb::value::type::signed32:
559 return rslt->get_signed32(0);
560 case mariadb::value::type::unsigned64:
561 case mariadb::value::type::signed64:
562 return rslt->get_signed64(0);
564 throw mariadb::exception::base(
"Value retrieved was not a long!");
569 throw mariadb::exception::base(
"No long value found in the database!");
572 template<
typename... Args>
573 bool dbconn::exists(mariadb::connection_ref connection,
const std::string& sql, Args&&... args)
575 mariadb::result_set_ref rslt = select(connection, sql, args...);
582 template<
typename... Args>
583 mariadb::result_set_ref
dbconn::select(mariadb::connection_ref connection,
const std::string& sql, Args&&... args)
587 mariadb::statement_ref stmt = query(connection, sql, args...);
588 mariadb::result_set_ref rslt = mariadb::result_set_ref(stmt->query());
591 catch(
const mariadb::exception::base& e)
593 ERR_SQL <<
"SQL query failed for query: `"+sql+
"`";
597 template<
typename... Args>
598 unsigned long long dbconn::modify(mariadb::connection_ref connection,
const std::string& sql, Args&&... args)
602 mariadb::statement_ref stmt = query(connection, sql, args...);
603 unsigned long long count = stmt->execute();
606 catch(
const mariadb::exception::base& e)
608 ERR_SQL <<
"SQL query failed for query: `"+sql+
"`";
612 template<
typename... Args>
613 unsigned long long dbconn::modify_get_id(mariadb::connection_ref connection,
const std::string& sql, Args&&... args)
617 mariadb::statement_ref stmt = query(connection, sql, args...);
618 unsigned long long count = stmt->insert();
621 catch(
const mariadb::exception::base& e)
623 ERR_SQL <<
"SQL query failed for query: `"+sql+
"`";
631 template<
typename... Args>
632 mariadb::statement_ref
dbconn::query(mariadb::connection_ref connection,
const std::string& sql, Args&&... args)
634 mariadb::statement_ref stmt = connection->create_statement(sql);
635 prepare(stmt, 0, args...);
639 template<
typename Arg,
typename... Args>
640 void dbconn::prepare(mariadb::statement_ref stmt,
int i, Arg arg, Args&&... args)
642 i = prepare(stmt, i, arg);
643 prepare(stmt, i, args...);
649 stmt->set_boolean(i++, arg);
655 stmt->set_signed32(i++, arg);
661 stmt->set_signed64(i++, arg);
665 int dbconn::prepare(mariadb::statement_ref stmt,
int i,
unsigned long long arg)
667 stmt->set_unsigned64(i++, arg);
671 int dbconn::prepare(mariadb::statement_ref stmt,
int i,
const char* arg)
673 stmt->set_string(i++, arg);
677 int dbconn::prepare(mariadb::statement_ref stmt,
int i, std::string arg)
679 stmt->set_string(i++, arg);
685 #endif //HAVE_MYSQLPP 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)
void update_logout(unsigned long long login_id)
void insert_addon_author(const std::string &instance_version, const std::string &id, const std::string author, int is_primary)
bool topic_id_exists(int topic_id)
void delete_addon_authors(const std::string &instance_version, const std::string &id)
std::string get_tournaments()
unsigned long long modify_get_id(mariadb::connection_ref connection, const std::string &sql, Args &&... args)
Executes non-select statements (ie: insert, update, delete), but primarily intended for inserts that ...
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 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'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)
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.
dbconn(const config &c)
Initializes the synchronous query connection as well as the account object that has the connection se...
bool do_any_authors_exist(const std::string &instance_version, const std::string &id)
bool exists(const image::locator &i_locator)
Returns true if the given image actually exists, without loading it.
virtual void read(mariadb::result_set_ref rslt)=0
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_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)
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)
void update_addon_download_count(const std::string &instance_version, const std::string &id, const std::string &version)
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)
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)
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 lowercase(const std::string &s)
Returns a lowercased version of the string.
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.
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 ¤t_user)
mariadb::result_set_ref select(mariadb::connection_ref connection, const std::string &sql, Args &&... args)
Executes a select statement.
ban_check get_ban_info(const std::string &name, const std::string &ip)
bool is_user_author(const std::string &instance_version, const std::string &id, const std::string &username, int is_primary)
A config object defines a single node in a WML file, with access to child nodes.
std::unique_ptr< simple_wml::document > to_doc()
unsigned long long insert_login(const std::string &username, const std::string &ip, const std::string &version)
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)