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