The Battle for Wesnoth  1.17.0-dev
dbconn.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2020 - 2021
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 #ifdef HAVE_MYSQLPP
16 
17 #include "server/common/dbconn.hpp"
21 
22 #include "log.hpp"
24 
25 static lg::log_domain log_sql_handler("sql_executor");
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)
30 
31 dbconn::dbconn(const config& c)
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 {
44  try
45  {
46  account_ = mariadb::account::create(c["db_host"].str(), c["db_user"].str(), c["db_password"].str());
47  account_->set_connect_option(mysql_option::MYSQL_SET_CHARSET_NAME, std::string("utf8mb4"));
48  account_->set_schema(c["db_name"].str());
49  // initialize the connection used to run synchronous queries.
50  connection_ = create_connection();
51  }
52  catch(const mariadb::exception::base& e)
53  {
54  log_sql_exception("Failed to connect to the database!", e);
55  }
56 }
57 
58 void dbconn::log_sql_exception(const std::string& text, const mariadb::exception::base& e)
59 {
60  ERR_SQL << text << '\n'
61  << "what: " << e.what() << '\n'
62  << "error id: " << e.error_id() << std::endl;
63 }
64 
65 mariadb::connection_ref dbconn::create_connection()
66 {
67  return mariadb::connection::create(account_);
68 }
69 
70 //
71 // queries
72 //
73 int dbconn::async_test_query(int limit)
74 {
75  std::string sql = "with recursive TEST(T) as "
76  "( "
77  "select 1 "
78  "union all "
79  "select T+1 from TEST where T < ? "
80  ") "
81  "select count(*) from TEST";
82  int t = get_single_long(create_connection(), sql, limit);
83  return t;
84 }
85 
86 std::string dbconn::get_uuid()
87 {
88  try
89  {
90  return get_single_string(connection_, "SELECT UUID()");
91  }
92  catch(const mariadb::exception::base& e)
93  {
94  log_sql_exception("Could not retrieve a UUID!", e);
95  return "";
96  }
97 }
98 
99 std::string dbconn::get_tournaments()
100 {
101  if(db_tournament_query_ == "")
102  {
103  return "";
104  }
105 
106  try
107  {
108  tournaments t;
109  get_complex_results(connection_, t, db_tournament_query_);
110  return t.str();
111  }
112  catch(const mariadb::exception::base& e)
113  {
114  log_sql_exception("Could not retrieve the tournaments!", e);
115  return "";
116  }
117 }
118 
119 std::unique_ptr<simple_wml::document> dbconn::get_game_history(int player_id, int offset)
120 {
121  try
122  {
123  std::string game_history_query = "select "
124 " game.GAME_NAME, "
125 " game.RELOAD, "
126 " game.START_TIME, "
127 " GROUP_CONCAT(CONCAT(player.USER_NAME, ':', player.FACTION)) as PLAYERS, "
128 " IFNULL(scenario.NAME, '') as SCENARIO_NAME, "
129 " IFNULL(scenario.ID, '') as SCENARIO_ID, "
130 " IFNULL(era.NAME, '') as ERA_NAME, "
131 " IFNULL(era.ID, '') as ERA_ID, "
132 " IFNULL(GROUP_CONCAT(distinct mods.NAME, '') as MODIFICATION_NAMES, "
133 " IFNULL(GROUP_CONCAT(distinct mods.ID), '') as MODIFICATION_IDS, "
134 " case "
135 " when game.PUBLIC = 1 "
136 " 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) "
137 " else '' "
138 " end as REPLAY_URL "
139 "from "+db_game_info_table_+" game "
140 "inner join "+db_game_player_info_table_+" player "
141 " on exists "
142 " ( "
143 " select 1 "
144 " from "+db_game_player_info_table_+" player1 "
145 " where game.INSTANCE_UUID = player1.INSTANCE_UUID "
146 " and game.GAME_ID = player1.GAME_ID "
147 " and player1.USER_ID = ? "
148 " ) "
149 " and game.INSTANCE_UUID = player.INSTANCE_UUID "
150 " and game.GAME_ID = player.GAME_ID "
151 " and player.USER_ID != -1 "
152 " and game.END_TIME is not NULL "
153 "inner join "+db_game_content_info_table_+" scenario "
154 " on scenario.TYPE = 'scenario' "
155 " and scenario.INSTANCE_UUID = game.INSTANCE_UUID "
156 " and scenario.GAME_ID = game.GAME_ID "
157 "inner join "+db_game_content_info_table_+" era "
158 " on era.TYPE = 'era' "
159 " and era.INSTANCE_UUID = game.INSTANCE_UUID "
160 " and era.GAME_ID = game.GAME_ID "
161 "left join "+db_game_content_info_table_+" mods "
162 " on mods.TYPE = 'modification' "
163 " and mods.INSTANCE_UUID = game.INSTANCE_UUID "
164 " and mods.GAME_ID = game.GAME_ID "
165 "group by game.INSTANCE_UUID, game.GAME_ID "
166 "order by game.START_TIME desc "
167 "limit 11 offset ? ";
168 
169  game_history gh;
170  get_complex_results(create_connection(), gh, game_history_query, player_id, offset);
171  return gh.to_doc();
172  }
173  catch(const mariadb::exception::base& e)
174  {
175  log_sql_exception("Could not retrieve the game history for forum ID `"+std::to_string(player_id)+"`!", e);
176  auto doc = std::make_unique<simple_wml::document>();
177  doc->set_attr("error", "Error retrieving game history.");
178  return doc;
179  }
180 }
181 
182 bool dbconn::user_exists(const std::string& name)
183 {
184  try
185  {
186  return exists(connection_, "SELECT 1 FROM `"+db_users_table_+"` WHERE UPPER(username)=UPPER(?)", name);
187  }
188  catch(const mariadb::exception::base& e)
189  {
190  log_sql_exception("Unable to check if user row for '"+name+"' exists!", e);
191  return false;
192  }
193 }
194 
195 long dbconn::get_forum_id(const std::string& name)
196 {
197  try
198  {
199  return get_single_long(connection_, "SELECT IFNULL((SELECT user_id FROM `"+db_users_table_+"` WHERE UPPER(username)=UPPER(?)), 0)", name);
200  }
201  catch(const mariadb::exception::base& e)
202  {
203  log_sql_exception("Unable to get user_id for '"+name+"'!", e);
204  return 0;
205  }
206 }
207 
208 bool dbconn::extra_row_exists(const std::string& name)
209 {
210  try
211  {
212  return exists(connection_, "SELECT 1 FROM `"+db_extra_table_+"` WHERE UPPER(username)=UPPER(?)", name);
213  }
214  catch(const mariadb::exception::base& e)
215  {
216  log_sql_exception("Unable to check if extra row for '"+name+"' exists!", e);
217  return false;
218  }
219 }
220 
221 bool dbconn::is_user_in_group(const std::string& name, int group_id)
222 {
223  try
224  {
225  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 = ?",
226  name, group_id);
227  }
228  catch(const mariadb::exception::base& e)
229  {
230  log_sql_exception("Unable to check if the user '"+name+"' is in group '"+std::to_string(group_id)+"'!", e);
231  return false;
232  }
233 }
234 
235 ban_check dbconn::get_ban_info(const std::string& name, const std::string& ip)
236 {
237  try
238  {
239  // selected ban_type value must be part of user_handler::BAN_TYPE
240  ban_check b;
241  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 >= ?)",
242  ip, name, name, std::time(nullptr));
243  return b;
244  }
245  catch(const mariadb::exception::base& e)
246  {
247  log_sql_exception("Failed to check ban info for user '"+name+"' connecting from ip '"+ip+"'!", e);
248  return ban_check();
249  }
250 }
251 
252 std::string dbconn::get_user_string(const std::string& table, const std::string& column, const std::string& name)
253 {
254  try
255  {
256  return get_single_string(connection_, "SELECT `"+column+"` from `"+table+"` WHERE UPPER(username)=UPPER(?)", name);
257  }
258  catch(const mariadb::exception::base& e)
259  {
260  log_sql_exception("Unable to query column `"+column+"` from table `"+table+"` for user `"+name+"`", e);
261  return "";
262  }
263 }
264 int dbconn::get_user_int(const std::string& table, const std::string& column, const std::string& name)
265 {
266  try
267  {
268  return static_cast<int>(get_single_long(connection_, "SELECT `"+column+"` from `"+table+"` WHERE UPPER(username)=UPPER(?)", name));
269  }
270  catch(const mariadb::exception::base& e)
271  {
272  log_sql_exception("Unable to query column `"+column+"` from table `"+table+"` for user `"+name+"`", e);
273  return 0;
274  }
275 }
276 void dbconn::write_user_int(const std::string& column, const std::string& name, int value)
277 {
278  try
279  {
280  if(!extra_row_exists(name))
281  {
282  modify(connection_, "INSERT INTO `"+db_extra_table_+"` VALUES(?,?,'0')", name, value);
283  }
284  modify(connection_, "UPDATE `"+db_extra_table_+"` SET "+column+"=? WHERE UPPER(username)=UPPER(?)", value, name);
285  }
286  catch(const mariadb::exception::base& e)
287  {
288  log_sql_exception("Unable to write `"+std::to_string(value)+"` to column `"+column+"` on table `"+db_extra_table_+"` for user `"+name+"`", e);
289  }
290 }
291 
292 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)
293 {
294  try
295  {
296  modify(connection_, "INSERT INTO `"+db_game_info_table_+"`(INSTANCE_UUID, GAME_ID, INSTANCE_VERSION, GAME_NAME, RELOAD, OBSERVERS, PUBLIC, PASSWORD) VALUES(?, ?, ?, ?, ?, ?, ?, ?)",
297  uuid, game_id, version, name, reload, observers, is_public, has_password);
298  }
299  catch(const mariadb::exception::base& e)
300  {
301  log_sql_exception("Failed to insert game info row for UUID `"+uuid+"` and game ID `"+std::to_string(game_id)+"`", e);
302  }
303 }
304 void dbconn::update_game_end(const std::string& uuid, int game_id, const std::string& replay_location)
305 {
306  try
307  {
308  modify(connection_, "UPDATE `"+db_game_info_table_+"` SET END_TIME = CURRENT_TIMESTAMP, REPLAY_NAME = ? WHERE INSTANCE_UUID = ? AND GAME_ID = ?",
309  replay_location, uuid, game_id);
310  }
311  catch(const mariadb::exception::base& e)
312  {
313  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);
314  }
315 }
316 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)
317 {
318  try
319  {
320  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), ?, ?, ?, ?, ?, ?)",
321  uuid, game_id, username, side_number, is_host, faction, version, source, current_user);
322  }
323  catch(const mariadb::exception::base& e)
324  {
325  log_sql_exception("Failed to insert game player info row for UUID `"+uuid+"` and game ID `"+std::to_string(game_id)+"`", e);
326  }
327 }
328 void 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& source, const std::string& version)
329 {
330  try
331  {
332  modify(connection_, "INSERT INTO `"+db_game_content_info_table_+"`(INSTANCE_UUID, GAME_ID, TYPE, NAME, ID, SOURCE, VERSION) VALUES(?, ?, ?, ?, ?, ?, ?)",
333  uuid, game_id, type, name, id, source, version);
334  }
335  catch(const mariadb::exception::base& e)
336  {
337  log_sql_exception("Failed to insert game content info row for UUID `"+uuid+"` and game ID `"+std::to_string(game_id)+"`", e);
338  }
339 }
340 void dbconn::set_oos_flag(const std::string& uuid, int game_id)
341 {
342  try
343  {
344  modify(connection_, "UPDATE `"+db_game_info_table_+"` SET OOS = 1 WHERE INSTANCE_UUID = ? AND GAME_ID = ?",
345  uuid, game_id);
346  }
347  catch(const mariadb::exception::base& e)
348  {
349  log_sql_exception("Failed to set the OOS flag for UUID `"+uuid+"` and game ID `"+std::to_string(game_id)+"`", e);
350  }
351 }
352 
353 bool dbconn::topic_id_exists(int topic_id) {
354  try
355  {
356  return exists(connection_, "SELECT 1 FROM `"+db_topics_table_+"` WHERE TOPIC_ID = ?",
357  topic_id);
358  }
359  catch(const mariadb::exception::base& e)
360  {
361  log_sql_exception("Unable to check whether `"+std::to_string(topic_id)+"` exists.", e);
362  return true;
363  }
364 }
365 
366 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)
367 {
368  try
369  {
370  modify(connection_, "INSERT INTO `"+db_addon_info_table_+"`(INSTANCE_VERSION, ADDON_ID, ADDON_NAME, TYPE, VERSION, FORUM_AUTH, FEEDBACK_TOPIC) VALUES(?, ?, ?, ?, ?, ?, ?)",
371  instance_version, id, name, type, version, forum_auth, topic_id);
372  }
373  catch(const mariadb::exception::base& e)
374  {
375  log_sql_exception("Unable to insert add-on info for add-on `"+id+"` for instance `"+instance_version+"`.", e);
376  }
377 }
378 
379 unsigned long long dbconn::insert_login(const std::string& username, const std::string& ip, const std::string& version)
380 {
381  try
382  {
383  return modify(connection_, "INSERT INTO `"+db_connection_history_table_+"`(USER_NAME, IP, VERSION) values(lower(?), ?, ?)",
384  username, ip, version);
385  }
386  catch(const mariadb::exception::base& e)
387  {
388  log_sql_exception("Unable to insert login row user `"+username+"` and ip `"+ip+"`.", e);
389  return 0;
390  }
391 }
392 
393 void dbconn::update_logout(unsigned long long login_id)
394 {
395  try
396  {
397  modify(connection_, "UPDATE `"+db_connection_history_table_+"` SET LOGOUT_TIME = CURRENT_TIMESTAMP WHERE LOGIN_ID = ?",
398  login_id);
399  }
400  catch(const mariadb::exception::base& e)
401  {
402  log_sql_exception("Unable to update login row `"+std::to_string(login_id)+"`.", e);
403  }
404 }
405 
406 void dbconn::get_users_for_ip(const std::string& ip, std::ostringstream* out)
407 {
408  try
409  {
410  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",
411  ip);
412 
413  *out << "\nCount of results for ip: " << rslt->row_count();
414 
415  while(rslt->next())
416  {
417  *out << "\nFound user " << rslt->get_string(0) << " with ip " << rslt->get_string(1)
418  << ", logged in at " << rslt->get_string(2) << " and logged out at " << rslt->get_string(3);
419  }
420  }
421  catch(const mariadb::exception::base& e)
422  {
423  log_sql_exception("Unable to select rows for ip `"+ip+"`.", e);
424  }
425 }
426 
427 void dbconn::get_ips_for_user(const std::string& username, std::ostringstream* out)
428 {
429  try
430  {
431  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",
432  utf8::lowercase(username));
433 
434  *out << "\nCount of results for user: " << rslt->row_count();
435 
436  while(rslt->next())
437  {
438  *out << "\nFound user " << rslt->get_string(0) << " with ip " << rslt->get_string(1)
439  << ", logged in at " << rslt->get_string(2) << " and logged out at " << rslt->get_string(3);
440  }
441  }
442  catch(const mariadb::exception::base& e)
443  {
444  log_sql_exception("Unable to select rows for player `"+username+"`.", e);
445  }
446 }
447 
448 //
449 // handle complex query results
450 //
451 template<typename... Args>
452 void dbconn::get_complex_results(mariadb::connection_ref connection, rs_base& base, const std::string& sql, Args&&... args)
453 {
454  mariadb::result_set_ref rslt = select(connection, sql, args...);
455  base.read(rslt);
456 }
457 //
458 // handle single values
459 //
460 template<typename... Args>
461 std::string dbconn::get_single_string(mariadb::connection_ref connection, const std::string& sql, Args&&... args)
462 {
463  mariadb::result_set_ref rslt = select(connection, sql, args...);
464  if(rslt->next())
465  {
466  return rslt->get_string(0);
467  }
468  else
469  {
470  throw mariadb::exception::base("No string value found in the database!");
471  }
472 }
473 template<typename... Args>
474 long dbconn::get_single_long(mariadb::connection_ref connection, const std::string& sql, Args&&... args)
475 {
476  mariadb::result_set_ref rslt = select(connection, sql, args...);
477  if(rslt->next())
478  {
479  // mariadbpp checks for strict integral equivalence, but we don't care
480  // so check the type beforehand, call the associated getter, and let it silently get upcast to a long if needed
481  // subselects also apparently return a decimal
482  switch(rslt->column_type(0))
483  {
484  case mariadb::value::type::decimal:
485  return static_cast<long>(rslt->get_decimal(0).float32());
486  case mariadb::value::type::unsigned8:
487  case mariadb::value::type::signed8:
488  return rslt->get_signed8(0);
489  case mariadb::value::type::unsigned16:
490  case mariadb::value::type::signed16:
491  return rslt->get_signed16(0);
492  case mariadb::value::type::unsigned32:
493  case mariadb::value::type::signed32:
494  return rslt->get_signed32(0);
495  case mariadb::value::type::unsigned64:
496  case mariadb::value::type::signed64:
497  return rslt->get_signed64(0);
498  default:
499  throw mariadb::exception::base("Value retrieved was not a long!");
500  }
501  }
502  else
503  {
504  throw mariadb::exception::base("No long value found in the database!");
505  }
506 }
507 template<typename... Args>
508 bool dbconn::exists(mariadb::connection_ref connection, const std::string& sql, Args&&... args)
509 {
510  mariadb::result_set_ref rslt = select(connection, sql, args...);
511  return rslt->next();
512 }
513 
514 //
515 // select or modify values
516 //
517 template<typename... Args>
518 mariadb::result_set_ref dbconn::select(mariadb::connection_ref connection, const std::string& sql, Args&&... args)
519 {
520  try
521  {
522  mariadb::statement_ref stmt = query(connection, sql, args...);
523  mariadb::result_set_ref rslt = mariadb::result_set_ref(stmt->query());
524  return rslt;
525  }
526  catch(const mariadb::exception::base& e)
527  {
528  ERR_SQL << "SQL query failed for query: `"+sql+"`" << std::endl;
529  throw e;
530  }
531 }
532 template<typename... Args>
533 unsigned long long dbconn::modify(mariadb::connection_ref connection, const std::string& sql, Args&&... args)
534 {
535  try
536  {
537  mariadb::statement_ref stmt = query(connection, sql, args...);
538  unsigned long long count = stmt->insert();
539  return count;
540  }
541  catch(const mariadb::exception::base& e)
542  {
543  ERR_SQL << "SQL query failed for query: `"+sql+"`" << std::endl;
544  throw e;
545  }
546 }
547 
548 
549 
550 
551 template<typename... Args>
552 mariadb::statement_ref dbconn::query(mariadb::connection_ref connection, const std::string& sql, Args&&... args)
553 {
554  mariadb::statement_ref stmt = connection->create_statement(sql);
555  prepare(stmt, 0, args...);
556  return stmt;
557 }
558 
559 template<typename Arg, typename... Args>
560 void dbconn::prepare(mariadb::statement_ref stmt, int i, Arg arg, Args&&... args)
561 {
562  i = prepare(stmt, i, arg);
563  prepare(stmt, i, args...);
564 }
565 
566 template<>
567 int dbconn::prepare(mariadb::statement_ref stmt, int i, bool arg)
568 {
569  stmt->set_boolean(i++, arg);
570  return i;
571 }
572 template<>
573 int dbconn::prepare(mariadb::statement_ref stmt, int i, int arg)
574 {
575  stmt->set_signed32(i++, arg);
576  return i;
577 }
578 template<>
579 int dbconn::prepare(mariadb::statement_ref stmt, int i, long arg)
580 {
581  stmt->set_signed64(i++, arg);
582  return i;
583 }
584 template<>
585 int dbconn::prepare(mariadb::statement_ref stmt, int i, unsigned long long arg)
586 {
587  stmt->set_unsigned64(i++, arg);
588  return i;
589 }
590 template<>
591 int dbconn::prepare(mariadb::statement_ref stmt, int i, const char* arg)
592 {
593  stmt->set_string(i++, arg);
594  return i;
595 }
596 template<>
597 int dbconn::prepare(mariadb::statement_ref stmt, int i, std::string arg)
598 {
599  stmt->set_string(i++, arg);
600  return i;
601 }
602 
603 void dbconn::prepare(mariadb::statement_ref, int){}
604 
605 #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.
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)
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)
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)
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...
#define b
bool exists(const image::locator &i_locator)
Returns true if the given image actually exists, without loading it.
Definition: picture.cpp:1011
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_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)
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 get_uuid()
std::size_t i
Definition: function.cpp:967
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::string str()
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.
Definition: unicode.cpp:52
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.
double t
Definition: astarsearch.cpp:65
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:40
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:61
mock_char c
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)