AzerothCore 3.3.5a
OpenSource WoW Emulator
Loading...
Searching...
No Matches
DBUpdater< T > Class Template Reference

#include "DBUpdater.h"

Public Types

using Path = std::filesystem::path
 

Public Member Functions

std::string GetConfigEntry ()
 
std::string GetTableName ()
 
std::string GetBaseFilesDirectory ()
 
bool IsEnabled (uint32 const updateMask)
 
std::string GetDBModuleName ()
 
std::string GetConfigEntry ()
 
std::string GetTableName ()
 
std::string GetBaseFilesDirectory ()
 
bool IsEnabled (uint32 const updateMask)
 
std::string GetDBModuleName ()
 
std::string GetConfigEntry ()
 
std::string GetTableName ()
 
std::string GetBaseFilesDirectory ()
 
bool IsEnabled (uint32 const updateMask)
 
std::string GetDBModuleName ()
 

Static Public Member Functions

static std::string GetConfigEntry ()
 
static std::string GetTableName ()
 
static std::string GetBaseFilesDirectory ()
 
static bool IsEnabled (uint32 const updateMask)
 
static BaseLocation GetBaseLocationType ()
 
static bool Create (DatabaseWorkerPool< T > &pool)
 
static bool Update (DatabaseWorkerPool< T > &pool, std::string_view modulesList={})
 
static bool Update (DatabaseWorkerPool< T > &pool, std::vector< std::string > const *setDirectories)
 
static bool Populate (DatabaseWorkerPool< T > &pool)
 
static std::string GetDBModuleName ()
 

Static Private Member Functions

static QueryResult Retrieve (DatabaseWorkerPool< T > &pool, std::string const &query)
 
static void Apply (DatabaseWorkerPool< T > &pool, std::string const &query)
 
static void ApplyFile (DatabaseWorkerPool< T > &pool, Path const &path)
 
static void ApplyFile (DatabaseWorkerPool< T > &pool, std::string const &host, std::string const &user, std::string const &password, std::string const &port_or_socket, std::string const &database, std::string const &ssl, Path const &path)
 

Detailed Description

template<class T>
class DBUpdater< T >

Member Typedef Documentation

◆ Path

template<class T >
using DBUpdater< T >::Path = std::filesystem::path

Member Function Documentation

◆ Apply()

template<class T >
void DBUpdater< T >::Apply ( DatabaseWorkerPool< T > &  pool,
std::string const &  query 
)
staticprivate
429{
430 pool.DirectExecute(query.c_str());
431}
void DirectExecute(std::string_view sql)
Definition: DatabaseWorkerPool.cpp:527

References DatabaseWorkerPool< T >::DirectExecute().

Referenced by DBUpdater< T >::Update().

◆ ApplyFile() [1/2]

template<class T >
void DBUpdater< T >::ApplyFile ( DatabaseWorkerPool< T > &  pool,
Path const &  path 
)
staticprivate
435{
438}
MySQLConnectionInfo const * GetConnectionInfo() const
Definition: DatabaseWorkerPool.h:71
std::string host
Definition: MySQLConnection.h:49
std::string port_or_socket
Definition: MySQLConnection.h:50
std::string user
Definition: MySQLConnection.h:46
std::string database
Definition: MySQLConnection.h:48
std::string ssl
Definition: MySQLConnection.h:51
std::string password
Definition: MySQLConnection.h:47
static void ApplyFile(DatabaseWorkerPool< T > &pool, Path const &path)
Definition: DBUpdater.cpp:434

References DBUpdater< T >::ApplyFile(), MySQLConnectionInfo::database, DatabaseWorkerPool< T >::GetConnectionInfo(), MySQLConnectionInfo::host, MySQLConnectionInfo::password, MySQLConnectionInfo::port_or_socket, MySQLConnectionInfo::ssl, and MySQLConnectionInfo::user.

Referenced by DBUpdater< T >::ApplyFile(), DBUpdater< T >::Create(), and DBUpdater< T >::Update().

◆ ApplyFile() [2/2]

template<class T >
void DBUpdater< T >::ApplyFile ( DatabaseWorkerPool< T > &  pool,
std::string const &  host,
std::string const &  user,
std::string const &  password,
std::string const &  port_or_socket,
std::string const &  database,
std::string const &  ssl,
Path const &  path 
)
staticprivate
443{
444 std::string configTempDir = sConfigMgr->GetOption<std::string>("TempDir", "");
445
446 auto tempDir = configTempDir.empty() ? std::filesystem::temp_directory_path().string() : configTempDir;
447
448 tempDir = Acore::String::AddSuffixIfNotExists(tempDir, std::filesystem::path::preferred_separator);
449
450 std::string confFileName = "mysql_ac.conf";
451
452 std::ofstream outfile (tempDir + confFileName);
453
454 outfile << "[client]\npassword = \"" << password << '"' << std::endl;
455
456 outfile.close();
457
458 std::vector<std::string> args;
459 args.reserve(9);
460
461 args.emplace_back("--defaults-extra-file="+tempDir + confFileName+"");
462
463 // CLI Client connection info
464 args.emplace_back("-h" + host);
465 args.emplace_back("-u" + user);
466
467 // Check if we want to connect through ip or socket (Unix only)
468#ifdef _WIN32
469
470 if (host == ".")
471 args.emplace_back("--protocol=PIPE");
472 else
473 args.emplace_back("-P" + port_or_socket);
474
475#else
476
477 if (!std::isdigit(port_or_socket[0]))
478 {
479 // We can't check if host == "." here, because it is named localhost if socket option is enabled
480 args.emplace_back("-P0");
481 args.emplace_back("--protocol=SOCKET");
482 args.emplace_back("-S" + port_or_socket);
483 }
484 else
485 // generic case
486 args.emplace_back("-P" + port_or_socket);
487
488#endif
489
490 // Set the default charset to utf8
491 args.emplace_back("--default-character-set=utf8");
492
493 // Set max allowed packet to 1 GB
494 args.emplace_back("--max-allowed-packet=1GB");
495
496 if (ssl == "ssl")
497 args.emplace_back("--ssl-mode=REQUIRED");
498
499 // Execute sql file
500 args.emplace_back("-e");
501 args.emplace_back(Acore::StringFormat("BEGIN; SOURCE {}; COMMIT;", path.generic_string()));
502
503 // Database
504 if (!database.empty())
505 args.emplace_back(database);
506
507 // Invokes a mysql process which doesn't leak credentials to logs
509 "sql.updates", "", true);
510
511 if (ret != EXIT_SUCCESS)
512 {
513 LOG_FATAL("sql.updates", "Applying of file \'{}\' to database \'{}\' failed!" \
514 " If you are a user, please pull the latest revision from the repository. "
515 "Also make sure you have not applied any of the databases with your sql client. "
516 "You cannot use auto-update system and import sql files from AzerothCore repository with your sql client. "
517 "If you are a developer, please fix your sql query.",
518 path.generic_string(), pool.GetConnectionInfo()->database);
519
520 throw UpdateException("update failed");
521 }
522}
#define LOG_FATAL(filterType__,...)
Definition: Log.h:153
#define sConfigMgr
Definition: Config.h:74
std::string StringFormat(FormatString< Args... > fmt, Args &&... args)
Default AC string format function.
Definition: StringFormat.h:34
int StartProcess(std::string const &executable, std::vector< std::string > const &args, std::string const &logger, std::string input_file, bool secure)
Definition: StartProcess.cpp:154
AC_COMMON_API std::string AddSuffixIfNotExists(std::string str, const char suffix)
Util function to add a suffix char. Can be used to add a slash at the end of a path.
Definition: StringFormat.cpp:73
Definition: DBUpdater.h:39
static std::string GetCorrectedMySQLExecutable()
Definition: DBUpdater.cpp:31

References Acore::String::AddSuffixIfNotExists(), MySQLConnectionInfo::database, DatabaseWorkerPool< T >::GetConnectionInfo(), DBUpdaterUtil::GetCorrectedMySQLExecutable(), LOG_FATAL, sConfigMgr, Acore::StartProcess(), and Acore::StringFormat().

◆ Create()

template<class T >
bool DBUpdater< T >::Create ( DatabaseWorkerPool< T > &  pool)
static
171{
172 LOG_WARN("sql.updates", "Database \"{}\" does not exist", pool.GetConnectionInfo()->database);
173
174 const char* disableInteractive = std::getenv("AC_DISABLE_INTERACTIVE");
175
176 if (!sConfigMgr->isDryRun() && (disableInteractive == nullptr || std::strcmp(disableInteractive, "1") != 0))
177 {
178 std::cout << "Do you want to create it? [yes (default) / no]:" << std::endl;
179 std::string answer;
180 std::getline(std::cin, answer);
181 if (!answer.empty() && !(answer.substr(0, 1) == "y"))
182 return false;
183 }
184
185 LOG_INFO("sql.updates", "Creating database \"{}\"...", pool.GetConnectionInfo()->database);
186
187 // Path of temp file
188 static Path const temp("create_table.sql");
189
190 // Create temporary query to use external MySQL CLi
191 std::ofstream file(temp.generic_string());
192 if (!file.is_open())
193 {
194 LOG_FATAL("sql.updates", "Failed to create temporary query file \"{}\"!", temp.generic_string());
195 return false;
196 }
197
198 file << "CREATE DATABASE `" << pool.GetConnectionInfo()->database << "` DEFAULT CHARACTER SET UTF8MB4 COLLATE utf8mb4_general_ci;\n\n";
199 file.close();
200
201 try
202 {
204 pool.GetConnectionInfo()->port_or_socket, "", pool.GetConnectionInfo()->ssl, temp);
205 }
206 catch (UpdateException&)
207 {
208 LOG_FATAL("sql.updates", "Failed to create database {}! Does the user (named in *.conf) have `CREATE`, `ALTER`, `DROP`, `INSERT` and `DELETE` privileges on the MySQL server?", pool.GetConnectionInfo()->database);
209 std::filesystem::remove(temp);
210 return false;
211 }
212
213 LOG_INFO("sql.updates", "Done.");
214 LOG_INFO("sql.updates", " ");
215 std::filesystem::remove(temp);
216 return true;
217}
#define LOG_INFO(filterType__,...)
Definition: Log.h:165
#define LOG_WARN(filterType__,...)
Definition: Log.h:161
std::filesystem::path Path
Definition: DBUpdater.h:71

References DBUpdater< T >::ApplyFile(), MySQLConnectionInfo::database, DatabaseWorkerPool< T >::GetConnectionInfo(), MySQLConnectionInfo::host, LOG_FATAL, LOG_INFO, LOG_WARN, MySQLConnectionInfo::password, MySQLConnectionInfo::port_or_socket, sConfigMgr, MySQLConnectionInfo::ssl, and MySQLConnectionInfo::user.

◆ GetBaseFilesDirectory() [1/4]

std::string DBUpdater< LoginDatabaseConnection >::GetBaseFilesDirectory ( )
81{
82 return BuiltInConfig::GetSourceDirectory() + "/data/sql/base/db_auth/";
83}
AC_COMMON_API std::string GetSourceDirectory()
Definition: BuiltInConfig.cpp:42

References BuiltInConfig::GetSourceDirectory().

◆ GetBaseFilesDirectory() [2/4]

std::string DBUpdater< WorldDatabaseConnection >::GetBaseFilesDirectory ( )
113{
114 return BuiltInConfig::GetSourceDirectory() + "/data/sql/base/db_world/";
115}

References BuiltInConfig::GetSourceDirectory().

◆ GetBaseFilesDirectory() [3/4]

std::string DBUpdater< CharacterDatabaseConnection >::GetBaseFilesDirectory ( )
145{
146 return BuiltInConfig::GetSourceDirectory() + "/data/sql/base/db_characters/";
147}

References BuiltInConfig::GetSourceDirectory().

◆ GetBaseFilesDirectory() [4/4]

template<class T >
static std::string DBUpdater< T >::GetBaseFilesDirectory ( )
static

◆ GetBaseLocationType()

template<class T >
BaseLocation DBUpdater< T >::GetBaseLocationType
static
165{
166 return LOCATION_REPOSITORY;
167}
@ LOCATION_REPOSITORY
Definition: DBUpdater.h:52

References LOCATION_REPOSITORY.

◆ GetConfigEntry() [1/4]

std::string DBUpdater< LoginDatabaseConnection >::GetConfigEntry ( )
69{
70 return "Updates.Auth";
71}

◆ GetConfigEntry() [2/4]

std::string DBUpdater< WorldDatabaseConnection >::GetConfigEntry ( )
101{
102 return "Updates.World";
103}

◆ GetConfigEntry() [3/4]

std::string DBUpdater< CharacterDatabaseConnection >::GetConfigEntry ( )
133{
134 return "Updates.Character";
135}

◆ GetConfigEntry() [4/4]

template<class T >
static std::string DBUpdater< T >::GetConfigEntry ( )
inlinestatic

◆ GetDBModuleName() [1/4]

std::string DBUpdater< LoginDatabaseConnection >::GetDBModuleName ( )
94{
95 return "db-auth";
96}

◆ GetDBModuleName() [2/4]

std::string DBUpdater< WorldDatabaseConnection >::GetDBModuleName ( )
126{
127 return "db-world";
128}

◆ GetDBModuleName() [3/4]

std::string DBUpdater< CharacterDatabaseConnection >::GetDBModuleName ( )
158{
159 return "db-characters";
160}

◆ GetDBModuleName() [4/4]

template<class T >
static std::string DBUpdater< T >::GetDBModuleName ( )
static

Referenced by DBUpdater< T >::Update().

◆ GetTableName() [1/4]

std::string DBUpdater< LoginDatabaseConnection >::GetTableName ( )
75{
76 return "Auth";
77}

◆ GetTableName() [2/4]

std::string DBUpdater< WorldDatabaseConnection >::GetTableName ( )
107{
108 return "World";
109}

◆ GetTableName() [3/4]

std::string DBUpdater< CharacterDatabaseConnection >::GetTableName ( )
139{
140 return "Character";
141}

◆ GetTableName() [4/4]

template<class T >
static std::string DBUpdater< T >::GetTableName ( )
inlinestatic

◆ IsEnabled() [1/4]

bool DBUpdater< LoginDatabaseConnection >::IsEnabled ( uint32 const  updateMask)
87{
88 // This way silences warnings under msvc
89 return (updateMask & DatabaseLoader::DATABASE_LOGIN) ? true : false;
90}
@ DATABASE_LOGIN
Definition: DatabaseLoader.h:48

References DatabaseLoader::DATABASE_LOGIN.

◆ IsEnabled() [2/4]

bool DBUpdater< WorldDatabaseConnection >::IsEnabled ( uint32 const  updateMask)
119{
120 // This way silences warnings under msvc
121 return (updateMask & DatabaseLoader::DATABASE_WORLD) ? true : false;
122}
@ DATABASE_WORLD
Definition: DatabaseLoader.h:50

References DatabaseLoader::DATABASE_WORLD.

◆ IsEnabled() [3/4]

bool DBUpdater< CharacterDatabaseConnection >::IsEnabled ( uint32 const  updateMask)
151{
152 // This way silences warnings under msvc
153 return (updateMask & DatabaseLoader::DATABASE_CHARACTER) ? true : false;
154}
@ DATABASE_CHARACTER
Definition: DatabaseLoader.h:49

References DatabaseLoader::DATABASE_CHARACTER.

◆ IsEnabled() [4/4]

template<class T >
static bool DBUpdater< T >::IsEnabled ( uint32 const  updateMask)
static

◆ Populate()

template<class T >
bool DBUpdater< T >::Populate ( DatabaseWorkerPool< T > &  pool)
static
357{
358 {
359 QueryResult const result = Retrieve(pool, "SHOW TABLES");
360 if (result && (result->GetRowCount() > 0))
361 return true;
362 }
363
365 return false;
366
367 LOG_INFO("sql.updates", "Database {} is empty, auto populating it...", DBUpdater<T>::GetTableName());
368
369 std::string const DirPathStr = DBUpdater<T>::GetBaseFilesDirectory();
370
371 Path const DirPath(DirPathStr);
372 if (!std::filesystem::is_directory(DirPath))
373 {
374 LOG_ERROR("sql.updates", ">> Directory \"{}\" not exist", DirPath.generic_string());
375 return false;
376 }
377
378 if (DirPath.empty())
379 {
380 LOG_ERROR("sql.updates", ">> Directory \"{}\" is empty", DirPath.generic_string());
381 return false;
382 }
383
384 std::filesystem::directory_iterator const DirItr;
385 uint32 FilesCount = 0;
386
387 for (std::filesystem::directory_iterator itr(DirPath); itr != DirItr; ++itr)
388 {
389 if (itr->path().extension() == ".sql")
390 FilesCount++;
391 }
392
393 if (!FilesCount)
394 {
395 LOG_ERROR("sql.updates", ">> In directory \"{}\" not exist '*.sql' files", DirPath.generic_string());
396 return false;
397 }
398
399 for (std::filesystem::directory_iterator itr(DirPath); itr != DirItr; ++itr)
400 {
401 if (itr->path().extension() != ".sql")
402 continue;
403
404 LOG_INFO("sql.updates", ">> Applying \'{}\'...", itr->path().filename().generic_string());
405
406 try
407 {
408 ApplyFile(pool, itr->path());
409 }
410 catch (UpdateException&)
411 {
412 return false;
413 }
414 }
415
416 LOG_INFO("sql.updates", ">> Done!");
417 LOG_INFO("sql.updates", " ");
418 return true;
419}
#define LOG_ERROR(filterType__,...)
Definition: Log.h:157
std::uint32_t uint32
Definition: Define.h:107
std::shared_ptr< ResultSet > QueryResult
Definition: DatabaseEnvFwd.h:27
static bool CheckExecutable()
Definition: DBUpdater.cpp:39
Definition: DBUpdater.h:69
static QueryResult Retrieve(DatabaseWorkerPool< T > &pool, std::string const &query)
Definition: DBUpdater.cpp:422
static std::string GetBaseFilesDirectory()

References DBUpdaterUtil::CheckExecutable(), DBUpdater< T >::GetBaseFilesDirectory(), LOG_ERROR, and LOG_INFO.

◆ Retrieve()

template<class T >
QueryResult DBUpdater< T >::Retrieve ( DatabaseWorkerPool< T > &  pool,
std::string const &  query 
)
staticprivate
423{
424 return pool.Query(query.c_str());
425}
QueryResult Query(std::string_view sql)
Definition: DatabaseWorkerPool.cpp:177

References DatabaseWorkerPool< T >::Query().

Referenced by DBUpdater< T >::Update().

◆ Update() [1/2]

template<class T >
bool DBUpdater< T >::Update ( DatabaseWorkerPool< T > &  pool,
std::string_view  modulesList = {} 
)
static
221{
223 return false;
224
225 LOG_INFO("sql.updates", "Updating {} database...", DBUpdater<T>::GetTableName());
226
227 Path const sourceDirectory(BuiltInConfig::GetSourceDirectory());
228
229 if (!is_directory(sourceDirectory))
230 {
231 LOG_ERROR("sql.updates", "DBUpdater: The given source directory {} does not exist, change the path to the directory where your sql directory exists (for example c:\\source\\azerothcore). Shutting down.",
232 sourceDirectory.generic_string());
233 return false;
234 }
235
236 auto CheckUpdateTable = [&](std::string const& tableName)
237 {
238 auto checkTable = DBUpdater<T>::Retrieve(pool, Acore::StringFormat("SHOW TABLES LIKE '{}'", tableName));
239 if (!checkTable)
240 {
241 LOG_WARN("sql.updates", "> Table '{}' not exist! Try add based table", tableName);
242
243 Path const temp(GetBaseFilesDirectory() + tableName + ".sql");
244
245 try
246 {
247 DBUpdater<T>::ApplyFile(pool, temp);
248 }
249 catch (UpdateException&)
250 {
251 LOG_FATAL("sql.updates", "Failed apply file to database {}! Does the user (named in *.conf) have `INSERT` and `DELETE` privileges on the MySQL server?", pool.GetConnectionInfo()->database);
252 return false;
253 }
254
255 return true;
256 }
257
258 return true;
259 };
260
261 if (!CheckUpdateTable("updates") || !CheckUpdateTable("updates_include"))
262 return false;
263
264 UpdateFetcher updateFetcher(sourceDirectory, [&](std::string const & query) { DBUpdater<T>::Apply(pool, query); },
265 [&](Path const & file) { DBUpdater<T>::ApplyFile(pool, file); },
266 [&](std::string const & query) -> QueryResult { return DBUpdater<T>::Retrieve(pool, query); }, DBUpdater<T>::GetDBModuleName(), modulesList);
267
268 UpdateResult result;
269 try
270 {
271 result = updateFetcher.Update(
272 sConfigMgr->GetOption<bool>("Updates.Redundancy", true),
273 sConfigMgr->GetOption<bool>("Updates.AllowRehash", true),
274 sConfigMgr->GetOption<bool>("Updates.ArchivedRedundancy", false),
275 sConfigMgr->GetOption<int32>("Updates.CleanDeadRefMaxCount", 3));
276 }
277 catch (UpdateException&)
278 {
279 return false;
280 }
281
282 std::string const info = Acore::StringFormat("Containing {} new and {} archived updates.", result.recent, result.archived);
283
284 if (!result.updated)
285 LOG_INFO("sql.updates", ">> {} database is up-to-date! {}", DBUpdater<T>::GetTableName(), info);
286 else
287 LOG_INFO("sql.updates", ">> Applied {} {}. {}", result.updated, result.updated == 1 ? "query" : "queries", info);
288
289 LOG_INFO("sql.updates", " ");
290
291 return true;
292}
std::int32_t int32
Definition: Define.h:103
static void Apply(DatabaseWorkerPool< T > &pool, std::string const &query)
Definition: DBUpdater.cpp:428
static std::string GetDBModuleName()
Definition: UpdateFetcher.h:30
Definition: UpdateFetcher.h:43

References DBUpdater< T >::Apply(), DBUpdater< T >::ApplyFile(), DBUpdaterUtil::CheckExecutable(), MySQLConnectionInfo::database, DatabaseWorkerPool< T >::GetConnectionInfo(), DBUpdater< T >::GetDBModuleName(), BuiltInConfig::GetSourceDirectory(), LOG_ERROR, LOG_FATAL, LOG_INFO, LOG_WARN, DBUpdater< T >::Retrieve(), sConfigMgr, and Acore::StringFormat().

◆ Update() [2/2]

template<class T >
bool DBUpdater< T >::Update ( DatabaseWorkerPool< T > &  pool,
std::vector< std::string > const *  setDirectories 
)
static
296{
298 {
299 return false;
300 }
301
302 Path const sourceDirectory(BuiltInConfig::GetSourceDirectory());
303 if (!is_directory(sourceDirectory))
304 {
305 return false;
306 }
307
308 auto CheckUpdateTable = [&](std::string const& tableName)
309 {
310 auto checkTable = DBUpdater<T>::Retrieve(pool, Acore::StringFormat("SHOW TABLES LIKE '{}'", tableName));
311 if (!checkTable)
312 {
313 Path const temp(GetBaseFilesDirectory() + tableName + ".sql");
314 try
315 {
316 DBUpdater<T>::ApplyFile(pool, temp);
317 }
318 catch (UpdateException&)
319 {
320 return false;
321 }
322
323 return true;
324 }
325
326 return true;
327 };
328
329 if (!CheckUpdateTable("updates") || !CheckUpdateTable("updates_include"))
330 {
331 return false;
332 }
333
334 UpdateFetcher updateFetcher(sourceDirectory, [&](std::string const & query) { DBUpdater<T>::Apply(pool, query); },
335 [&](Path const & file) { DBUpdater<T>::ApplyFile(pool, file); },
336 [&](std::string const & query) -> QueryResult { return DBUpdater<T>::Retrieve(pool, query); }, DBUpdater<T>::GetDBModuleName(), setDirectories);
337
338 UpdateResult result;
339 try
340 {
341 result = updateFetcher.Update(
342 sConfigMgr->GetOption<bool>("Updates.Redundancy", true),
343 sConfigMgr->GetOption<bool>("Updates.AllowRehash", true),
344 sConfigMgr->GetOption<bool>("Updates.ArchivedRedundancy", false),
345 sConfigMgr->GetOption<int32>("Updates.CleanDeadRefMaxCount", 3));
346 }
347 catch (UpdateException&)
348 {
349 return false;
350 }
351
352 return true;
353}

References DBUpdater< T >::Apply(), DBUpdater< T >::ApplyFile(), DBUpdaterUtil::CheckExecutable(), DBUpdater< T >::GetDBModuleName(), BuiltInConfig::GetSourceDirectory(), DBUpdater< T >::Retrieve(), sConfigMgr, and Acore::StringFormat().