The Battle for Wesnoth  1.17.6+dev
dbconn.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2020 - 2022
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();
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 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& source, const std::string& version)
329 {
330  try
331  {
332  return 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  return 0;
339  }
340 }
341 void dbconn::set_oos_flag(const std::string& uuid, int game_id)
342 {
343  try
344  {
345  modify(connection_, "UPDATE `"+db_game_info_table_+"` SET OOS = 1 WHERE INSTANCE_UUID = ? AND GAME_ID = ?",
346  uuid, game_id);
347  }
348  catch(const mariadb::exception::base& e)
349  {
350  log_sql_exception("Failed to set the OOS flag for UUID `"+uuid+"` and game ID `"+std::to_string(game_id)+"`", e);
351  }
352 }
353 
354 bool dbconn::topic_id_exists(int topic_id) {
355  try
356  {
357  return exists(connection_, "SELECT 1 FROM `"+db_topics_table_+"` WHERE TOPIC_ID = ?",
358  topic_id);
359  }
360  catch(const mariadb::exception::base& e)
361  {
362  log_sql_exception("Unable to check whether `"+std::to_string(topic_id)+"` exists.", e);
363  return true;
364  }
365 }
366 
367 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)
368 {
369  try
370  {
371  modify(connection_, "INSERT INTO `"+db_addon_info_table_+"`(INSTANCE_VERSION, ADDON_ID, ADDON_NAME, TYPE, VERSION, FORUM_AUTH, FEEDBACK_TOPIC) VALUES(?, ?, ?, ?, ?, ?, ?)",
372  instance_version, id, name, type, version, forum_auth, topic_id);
373  }
374  catch(const mariadb::exception::base& e)
375  {
376  log_sql_exception("Unable to insert add-on info for add-on `"+id+"` for instance `"+instance_version+"`.", e);
377  }
378 }
379 
380 unsigned long long dbconn::insert_login(const std::string& username, const std::string& ip, const std::string& version)
381 {
382  try
383  {
384  return modify_get_id(connection_, "INSERT INTO `"+db_connection_history_table_+"`(USER_NAME, IP, VERSION) values(lower(?), ?, ?)",
385  username, ip, version);
386  }
387  catch(const mariadb::exception::base& e)
388  {
389  log_sql_exception("Unable to insert login row user `"+username+"` and ip `"+ip+"`.", e);
390  return 0;
391  }
392 }
393 
394 void dbconn::update_logout(unsigned long long login_id)
395 {
396  try
397  {
398  modify(connection_, "UPDATE `"+db_connection_history_table_+"` SET LOGOUT_TIME = CURRENT_TIMESTAMP WHERE LOGIN_ID = ?",
399  login_id);
400  }
401  catch(const mariadb::exception::base& e)
402  {
403  log_sql_exception("Unable to update login row `"+std::to_string(login_id)+"`.", e);
404  }
405 }
406 
407 void dbconn::get_users_for_ip(const std::string& ip, std::ostringstream* out)
408 {
409  try
410  {
411  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",
412  ip);
413 
414  *out << "\nCount of results for ip: " << rslt->row_count();
415 
416  while(rslt->next())
417  {
418  *out << "\nFound user " << rslt->get_string(0) << " with ip " << rslt->get_string(1)
419  << ", logged in at " << rslt->get_string(2) << " and logged out at " << rslt->get_string(3);
420  }
421  }
422  catch(const mariadb::exception::base& e)
423  {
424  log_sql_exception("Unable to select rows for ip `"+ip+"`.", e);
425  }
426 }
427 
428 void dbconn::get_ips_for_user(const std::string& username, std::ostringstream* out)
429 {
430  try
431  {
432  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",
433  utf8::lowercase(username));
434 
435  *out << "\nCount of results for user: " << rslt->row_count();
436 
437  while(rslt->next())
438  {
439  *out << "\nFound user " << rslt->get_string(0) << " with ip " << rslt->get_string(1)
440  << ", logged in at " << rslt->get_string(2) << " and logged out at " << rslt->get_string(3);
441  }
442  }
443  catch(const mariadb::exception::base& e)
444  {
445  log_sql_exception("Unable to select rows for player `"+username+"`.", e);
446  }
447 }
448 
449 void dbconn::update_addon_download_count(const std::string& instance_version, const std::string& id, const std::string& version)
450 {
451  try
452  {
453  modify(connection_, "UPDATE `"+db_addon_info_table_+"` SET DOWNLOAD_COUNT = DOWNLOAD_COUNT+1 WHERE INSTANCE_VERSION = ? AND ADDON_ID = ? AND VERSION = ?",
454  instance_version, id, version);
455  }
456  catch(const mariadb::exception::base& e)
457  {
458  log_sql_exception("Unable to update download count for add-on "+id+" with version "+version+".", e);
459  }
460 }
461 
462 //
463 // handle complex query results
464 //
465 template<typename... Args>
466 void dbconn::get_complex_results(mariadb::connection_ref connection, rs_base& base, const std::string& sql, Args&&... args)
467 {
468  mariadb::result_set_ref rslt = select(connection, sql, args...);
469  base.read(rslt);
470 }
471 //
472 // handle single values
473 //
474 template<typename... Args>
475 std::string dbconn::get_single_string(mariadb::connection_ref connection, const std::string& sql, Args&&... args)
476 {
477  mariadb::result_set_ref rslt = select(connection, sql, args...);
478  if(rslt->next())
479  {
480  return rslt->get_string(0);
481  }
482  else
483  {
484  throw mariadb::exception::base("No string value found in the database!");
485  }
486 }
487 template<typename... Args>
488 long dbconn::get_single_long(mariadb::connection_ref connection, const std::string& sql, Args&&... args)
489 {
490  mariadb::result_set_ref rslt = select(connection, sql, args...);
491  if(rslt->next())
492  {
493  // mariadbpp checks for strict integral equivalence, but we don't care
494  // so check the type beforehand, call the associated getter, and let it silently get upcast to a long if needed
495  // subselects also apparently return a decimal
496  switch(rslt->column_type(0))
497  {
498  case mariadb::value::type::decimal:
499  return static_cast<long>(rslt->get_decimal(0).float32());
500  case mariadb::value::type::unsigned8:
501  case mariadb::value::type::signed8:
502  return rslt->get_signed8(0);
503  case mariadb::value::type::unsigned16:
504  case mariadb::value::type::signed16:
505  return rslt->get_signed16(0);
506  case mariadb::value::type::unsigned32:
507  case mariadb::value::type::signed32:
508  return rslt->get_signed32(0);
509  case mariadb::value::type::unsigned64:
510  case mariadb::value::type::signed64:
511  return rslt->get_signed64(0);
512  default:
513  throw mariadb::exception::base("Value retrieved was not a long!");
514  }
515  }
516  else
517  {
518  throw mariadb::exception::base("No long value found in the database!");
519  }
520 }
521 template<typename... Args>
522 bool dbconn::exists(mariadb::connection_ref connection, const std::string& sql, Args&&... args)
523 {
524  mariadb::result_set_ref rslt = select(connection, sql, args...);
525  return rslt->next();
526 }
527 
528 //
529 // select or modify values
530 //
531 template<typename... Args>
532 mariadb::result_set_ref dbconn::select(mariadb::connection_ref connection, const std::string& sql, Args&&... args)
533 {
534  try
535  {
536  mariadb::statement_ref stmt = query(connection, sql, args...);
537  mariadb::result_set_ref rslt = mariadb::result_set_ref(stmt->query());
538  return rslt;
539  }
540  catch(const mariadb::exception::base& e)
541  {
542  ERR_SQL << "SQL query failed for query: `"+sql+"`";
543  throw e;
544  }
545 }
546 template<typename... Args>
547 unsigned long long dbconn::modify(mariadb::connection_ref connection, const std::string& sql, Args&&... args)
548 {
549  try
550  {
551  mariadb::statement_ref stmt = query(connection, sql, args...);
552  unsigned long long count = stmt->execute();
553  return count;
554  }
555  catch(const mariadb::exception::base& e)
556  {
557  ERR_SQL << "SQL query failed for query: `"+sql+"`";
558  throw e;
559  }
560 }
561 template<typename... Args>
562 unsigned long long dbconn::modify_get_id(mariadb::connection_ref connection, const std::string& sql, Args&&... args)
563 {
564  try
565  {
566  mariadb::statement_ref stmt = query(connection, sql, args...);
567  unsigned long long count = stmt->insert();
568  return count;
569  }
570  catch(const mariadb::exception::base& e)
571  {
572  ERR_SQL << "SQL query failed for query: `"+sql+"`";
573  throw e;
574  }
575 }
576 
577 
578 
579 
580 template<typename... Args>
581 mariadb::statement_ref dbconn::query(mariadb::connection_ref connection, const std::string& sql, Args&&... args)
582 {
583  mariadb::statement_ref stmt = connection->create_statement(sql);
584  prepare(stmt, 0, args...);
585  return stmt;
586 }
587 
588 template<typename Arg, typename... Args>
589 void dbconn::prepare(mariadb::statement_ref stmt, int i, Arg arg, Args&&... args)
590 {
591  i = prepare(stmt, i, arg);
592  prepare(stmt, i, args...);
593 }
594 
595 template<>
596 int dbconn::prepare(mariadb::statement_ref stmt, int i, bool arg)
597 {
598  stmt->set_boolean(i++, arg);
599  return i;
600 }
601 template<>
602 int dbconn::prepare(mariadb::statement_ref stmt, int i, int arg)
603 {
604  stmt->set_signed32(i++, arg);
605  return i;
606 }
607 template<>
608 int dbconn::prepare(mariadb::statement_ref stmt, int i, long arg)
609 {
610  stmt->set_signed64(i++, arg);
611  return i;
612 }
613 template<>
614 int dbconn::prepare(mariadb::statement_ref stmt, int i, unsigned long long arg)
615 {
616  stmt->set_unsigned64(i++, arg);
617  return i;
618 }
619 template<>
620 int dbconn::prepare(mariadb::statement_ref stmt, int i, const char* arg)
621 {
622  stmt->set_string(i++, arg);
623  return i;
624 }
625 template<>
626 int dbconn::prepare(mariadb::statement_ref stmt, int i, std::string arg)
627 {
628  stmt->set_string(i++, arg);
629  return i;
630 }
631 
632 void dbconn::prepare(mariadb::statement_ref, int){}
633 
634 #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()
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&#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)
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 &source, const std::string &version)
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:1030
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.
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)
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:60
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)