AzerothCore 3.3.5a
OpenSource WoW Emulator
Loading...
Searching...
No Matches
PlayerDump.cpp File Reference
#include "PlayerDump.h"
#include "AccountMgr.h"
#include "CharacterCache.h"
#include "Common.h"
#include "DatabaseEnv.h"
#include "Log.h"
#include "ObjectMgr.h"
#include "Player.h"
#include "StringConvert.h"
#include "World.h"
#include <fstream>
#include <sstream>

Go to the source code of this file.

Classes

struct  FileCloser
 
struct  BaseTable
 
struct  DumpTable
 
class  StringTransaction
 
struct  TableField
 
struct  TableStruct
 

Typedefs

typedef std::unique_ptr< FILE, FileCloserFileHandle
 

Enumerations

enum  GuidType : uint8 {
  GUID_TYPE_ACCOUNT ,
  GUID_TYPE_CHAR ,
  GUID_TYPE_PET ,
  GUID_TYPE_MAIL ,
  GUID_TYPE_ITEM ,
  GUID_TYPE_EQUIPMENT_SET ,
  GUID_TYPE_NULL
}
 

Functions

FileHandle GetFileHandle (char const *path, char const *mode)
 
bool StringsEqualCaseInsensitive (std::string const &left, std::string const &right)
 
auto FindColumnByName (TableStruct &tableStruct, std::string const &columnName) -> decltype(tableStruct.TableFields.begin())
 
int32 GetColumnIndexByName (TableStruct const &tableStruct, std::string const &columnName)
 
void MarkDependentColumn (TableStruct &tableStruct, std::string const &columnName, GuidType dependentType)
 
void MarkWhereField (TableStruct &tableStruct, std::string const &whereField)
 
void AssertBaseTable (BaseTable const &baseTable)
 
bool FindColumn (TableStruct const &ts, std::string const &str, std::string const &column, std::string::size_type &s, std::string::size_type &e)
 
std::string GetTableName (std::string const &str)
 
bool ValidateFields (TableStruct const &ts, std::string const &str, size_t lineNumber)
 
bool ChangeColumn (TableStruct const &ts, std::string &str, std::string const &column, std::string const &with, bool allowZero=false)
 
std::string GetColumn (TableStruct const &ts, std::string &str, std::string const &column)
 
template<typename T , template< class, class, class... > class MapType, class... Rest>
RegisterNewGuid (T oldGuid, MapType< T, T, Rest... > &guidMap, T guidOffset)
 
template<typename T , template< class, class, class... > class MapType, class... Rest>
bool ChangeGuid (TableStruct const &ts, std::string &str, std::string const &column, MapType< T, T, Rest... > &guidMap, T guidOffset, bool allowZero=false)
 
void AppendTableDump (StringTransaction &trans, TableStruct const &tableStruct, QueryResult result)
 
std::string GenerateWhereStr (std::string const &field, ObjectGuid::LowType guid)
 
template<typename T , template< class, class... > class SetType, class... Rest>
std::string GenerateWhereStr (std::string const &field, SetType< T, Rest... > const &guidSet)
 
void FixNULLfields (std::string &line)
 

Variables

BaseTable const BaseTables []
 
DumpTable const DumpTables []
 
uint32 const DUMP_TABLE_COUNT = std::extent<decltype(DumpTables)>::value
 
std::vector< TableStructCharacterTables
 

Typedef Documentation

◆ FileHandle

typedef std::unique_ptr<FILE, FileCloser> FileHandle

Enumeration Type Documentation

◆ GuidType

enum GuidType : uint8
Enumerator
GUID_TYPE_ACCOUNT 
GUID_TYPE_CHAR 
GUID_TYPE_PET 
GUID_TYPE_MAIL 
GUID_TYPE_ITEM 
GUID_TYPE_EQUIPMENT_SET 
GUID_TYPE_NULL 
33{
34 // 32 bit long guids
40
41 // 64 bit long guids
43
44 // special types
45 GUID_TYPE_NULL // set to null
46};
@ GUID_TYPE_NULL
Definition: PlayerDump.cpp:45
@ GUID_TYPE_MAIL
Definition: PlayerDump.cpp:38
@ GUID_TYPE_PET
Definition: PlayerDump.cpp:37
@ GUID_TYPE_EQUIPMENT_SET
Definition: PlayerDump.cpp:42
@ GUID_TYPE_CHAR
Definition: PlayerDump.cpp:36
@ GUID_TYPE_ITEM
Definition: PlayerDump.cpp:39
@ GUID_TYPE_ACCOUNT
Definition: PlayerDump.cpp:35

Function Documentation

◆ AppendTableDump()

void AppendTableDump ( StringTransaction trans,
TableStruct const &  tableStruct,
QueryResult  result 
)
inline
519{
520 if (!result)
521 return;
522
523 do
524 {
525 std::ostringstream ss;
526 ss << "INSERT INTO `" << tableStruct.TableName << "` (";
527 for (auto itr = tableStruct.TableFields.begin(); itr != tableStruct.TableFields.end();)
528 {
529 ss << '`' << itr->FieldName << '`';
530 ++itr;
531
532 if (itr != tableStruct.TableFields.end())
533 ss << ", ";
534 }
535 ss << ") VALUES (";
536
537 uint32 const fieldSize = uint32(tableStruct.TableFields.size());
538 Field* fields = result->Fetch();
539
540 for (uint32 i = 0; i < fieldSize;)
541 {
542 std::string cString = fields[i].Get<std::string>();
543 ++i;
544
545 // null pointer -> we have null
546 if (cString.empty())
547 ss << "'NULL'";
548 else
549 {
550 std::string s(cString);
551 CharacterDatabase.EscapeString(s);
552 ss << '\'' << s << '\'';
553 }
554
555 if (i != fieldSize)
556 ss << ", ";
557 }
558 ss << ");";
559
560 trans.Append(ss.str().c_str());
561 } while (result->NextRow());
562}
std::uint32_t uint32
Definition: Define.h:108
DatabaseWorkerPool< CharacterDatabaseConnection > CharacterDatabase
Accessor to the character database.
Definition: DatabaseEnv.cpp:21
Class used to access individual fields of database query result.
Definition: Field.h:99
std::enable_if_t< std::is_arithmetic_v< T >, T > Get() const
Definition: Field.h:113
void Append(char const *sql)
Definition: PlayerDump.cpp:131

References StringTransaction::Append(), CharacterDatabase, Field::Get(), TableStruct::TableFields, and TableStruct::TableName.

Referenced by PlayerDumpWriter::AppendTable().

◆ AssertBaseTable()

void AssertBaseTable ( BaseTable const &  baseTable)
inline
238{
239 auto itr = std::find_if(CharacterTables.begin(), CharacterTables.end(), [baseTable](TableStruct const& tableStruct) -> bool
240 {
241 return StringsEqualCaseInsensitive(tableStruct.TableName, baseTable.TableName);
242 });
243
244 ASSERT(itr != CharacterTables.end());
245
246 auto columnItr = FindColumnByName(*itr, baseTable.PrimaryKey);
247 ASSERT(columnItr != itr->TableFields.end());
248
249 columnItr = FindColumnByName(*itr, baseTable.PlayerGuid);
250 ASSERT(columnItr != itr->TableFields.end());
251}
#define ASSERT
Definition: Errors.h:68
std::vector< TableStruct > CharacterTables
Definition: PlayerDump.cpp:166
auto FindColumnByName(TableStruct &tableStruct, std::string const &columnName) -> decltype(tableStruct.TableFields.begin())
Definition: PlayerDump.cpp:181
Definition: PlayerDump.cpp:157

References ASSERT, CharacterTables, FindColumnByName(), BaseTable::PlayerGuid, and BaseTable::PrimaryKey.

Referenced by PlayerDump::InitializeTables().

◆ ChangeColumn()

bool ChangeColumn ( TableStruct const &  ts,
std::string &  str,
std::string const &  column,
std::string const &  with,
bool  allowZero = false 
)
inline
471{
472 std::string::size_type s, e;
473 if (!FindColumn(ts, str, column, s, e))
474 return false;
475
476 if (allowZero && str.substr(s, e - s) == "0")
477 return true; // not an error
478
479 str.replace(s, e - s, with);
480 return true;
481}
bool FindColumn(TableStruct const &ts, std::string const &str, std::string const &column, std::string::size_type &s, std::string::size_type &e)
Definition: PlayerDump.cpp:383

References FindColumn().

Referenced by ChangeGuid(), and PlayerDumpReader::LoadDump().

◆ ChangeGuid()

template<typename T , template< class, class, class... > class MapType, class... Rest>
bool ChangeGuid ( TableStruct const &  ts,
std::string &  str,
std::string const &  column,
MapType< T, T, Rest... > &  guidMap,
guidOffset,
bool  allowZero = false 
)
inline
506{
507 T oldGuid(*Acore::StringTo<uint64>(GetColumn(ts, str, column)));
508 if (allowZero && !oldGuid)
509 return true; // not an error
510
511 std::string chritem;
512 T newGuid = RegisterNewGuid(oldGuid, guidMap, guidOffset);
513 chritem = std::to_string(newGuid);
514
515 return ChangeColumn(ts, str, column, chritem, allowZero);
516}
std::string GetColumn(TableStruct const &ts, std::string &str, std::string const &column)
Definition: PlayerDump.cpp:483
bool ChangeColumn(TableStruct const &ts, std::string &str, std::string const &column, std::string const &with, bool allowZero=false)
Definition: PlayerDump.cpp:470
T RegisterNewGuid(T oldGuid, MapType< T, T, Rest... > &guidMap, T guidOffset)
Definition: PlayerDump.cpp:493

References ChangeColumn(), GetColumn(), and RegisterNewGuid().

Referenced by PlayerDumpReader::LoadDump().

◆ FindColumn()

bool FindColumn ( TableStruct const &  ts,
std::string const &  str,
std::string const &  column,
std::string::size_type &  s,
std::string::size_type &  e 
)
inline
384{
385 int32 columnIndex = GetColumnIndexByName(ts, column);
386 if (columnIndex == -1)
387 return false;
388
389 // array indices start at 0, compensate
390 ++columnIndex;
391
392 s = str.find("VALUES ('");
393 if (s == std::string::npos)
394 return false;
395 s += 9;
396
397 do
398 {
399 e = str.find('\'', s);
400 if (e == std::string::npos)
401 return false;
402 } while (str[e - 1] == '\\');
403
404 for (int32 i = 1; i < columnIndex; ++i)
405 {
406 do
407 {
408 // length of "', '"
409 s = e + 4;
410 e = str.find('\'', s);
411 if (e == std::string::npos)
412 return false;
413 } while (str[e - 1] == '\\');
414 }
415 return true;
416}
std::int32_t int32
Definition: Define.h:104
int32 GetColumnIndexByName(TableStruct const &tableStruct, std::string const &columnName)
Definition: PlayerDump.cpp:189

References GetColumnIndexByName().

Referenced by ChangeColumn(), and GetColumn().

◆ FindColumnByName()

auto FindColumnByName ( TableStruct tableStruct,
std::string const &  columnName 
) -> decltype(tableStruct.TableFields.begin())
inline
182{
183 return std::find_if(tableStruct.TableFields.begin(), tableStruct.TableFields.end(), [columnName](TableField const& tableField) -> bool
184 {
185 return StringsEqualCaseInsensitive(tableField.FieldName, columnName);
186 });
187}
Definition: PlayerDump.cpp:149
std::vector< TableField > TableFields
Definition: PlayerDump.cpp:160

Referenced by AssertBaseTable(), MarkDependentColumn(), and MarkWhereField().

◆ FixNULLfields()

void FixNULLfields ( std::string &  line)
inline
754{
755 static std::string const NullString("'NULL'");
756 size_t pos = line.find(NullString);
757 while (pos != std::string::npos)
758 {
759 line.replace(pos, NullString.length(), "NULL");
760 pos = line.find(NullString);
761 }
762}

Referenced by PlayerDumpReader::LoadDump().

◆ GenerateWhereStr() [1/2]

std::string GenerateWhereStr ( std::string const &  field,
ObjectGuid::LowType  guid 
)
inline
565{
566 std::ostringstream whereStr;
567 whereStr << field << " = '" << guid << '\'';
568 return whereStr.str();
569}

Referenced by PlayerDumpWriter::AppendTable(), and PlayerDumpWriter::PopulateGuids().

◆ GenerateWhereStr() [2/2]

template<typename T , template< class, class... > class SetType, class... Rest>
std::string GenerateWhereStr ( std::string const &  field,
SetType< T, Rest... > const &  guidSet 
)
inline
573{
574 std::ostringstream whereStr;
575 whereStr << field << " IN ('";
576 for (auto itr = guidSet.begin(); itr != guidSet.end();)
577 {
578 whereStr << *itr;
579 ++itr;
580
581 if (whereStr.str().size() > MAX_QUERY_LEN - 50) // near to max query
582 break;
583
584 if (itr != guidSet.end())
585 whereStr << "','";
586 }
587 whereStr << "')";
588 return whereStr.str();
589}
#define MAX_QUERY_LEN
Definition: Common.h:91

References MAX_QUERY_LEN.

◆ GetColumn()

std::string GetColumn ( TableStruct const &  ts,
std::string &  str,
std::string const &  column 
)
inline
484{
485 std::string::size_type s, e;
486 if (!FindColumn(ts, str, column, s, e))
487 return "";
488
489 return str.substr(s, e - s);
490}

References FindColumn().

Referenced by ChangeGuid(), and PlayerDumpReader::LoadDump().

◆ GetColumnIndexByName()

int32 GetColumnIndexByName ( TableStruct const &  tableStruct,
std::string const &  columnName 
)
inline
190{
191 auto itr = tableStruct.FieldIndices.find(columnName);
192 if (itr == tableStruct.FieldIndices.end())
193 return -1;
194
195 return itr->second;
196}

References TableStruct::FieldIndices.

Referenced by PlayerDumpWriter::AppendTable(), FindColumn(), and ValidateFields().

◆ GetFileHandle()

FileHandle GetFileHandle ( char const *  path,
char const *  mode 
)
inline
60{
61 return FileHandle(fopen(path, mode), FileCloser());
62}
std::unique_ptr< FILE, FileCloser > FileHandle
Definition: PlayerDump.cpp:57
Definition: PlayerDump.cpp:50

Referenced by PlayerDumpWriter::WriteDumpToFile().

◆ GetTableName()

std::string GetTableName ( std::string const &  str)
inline
419{
420 // length of "INSERT INTO `"
421 static std::string::size_type const s = 13;
422 std::string::size_type e = str.find('`', s);
423 if (e == std::string::npos)
424 return "";
425
426 return str.substr(s, e - s);
427}

Referenced by PlayerDumpReader::LoadDump().

◆ MarkDependentColumn()

void MarkDependentColumn ( TableStruct tableStruct,
std::string const &  columnName,
GuidType  dependentType 
)
inline
199{
200 auto itr = FindColumnByName(tableStruct, columnName);
201 if (itr == tableStruct.TableFields.end())
202 {
203 LOG_FATAL("server.loading", "Column `{}` declared in table `{}` marked as dependent but doesn't exist, PlayerDump will not work properly, please update table definitions",
204 columnName, tableStruct.TableName);
205 ABORT();
206 return;
207 }
208
209 if (itr->IsDependentField)
210 {
211 LOG_FATAL("server.loading", "Attempt to mark column `{}` in table `{}` as dependent column but already marked! please check your code.",
212 columnName, tableStruct.TableName);
213 ABORT();
214 return;
215 }
216
217 itr->IsDependentField = true;
218 itr->FieldGuidType = dependentType;
219}
#define ABORT
Definition: Errors.h:76
#define LOG_FATAL(filterType__,...)
Definition: Log.h:153
std::string TableName
Definition: PlayerDump.cpp:158

References ABORT, FindColumnByName(), LOG_FATAL, TableStruct::TableFields, and TableStruct::TableName.

Referenced by PlayerDump::InitializeTables().

◆ MarkWhereField()

void MarkWhereField ( TableStruct tableStruct,
std::string const &  whereField 
)
inline
222{
223 ASSERT(tableStruct.WhereFieldName.empty());
224
225 auto whereFieldItr = FindColumnByName(tableStruct, whereField);
226 if (whereFieldItr == tableStruct.TableFields.end())
227 {
228 LOG_FATAL("server.loading", "Column name `{}` set as 'WHERE' column for table `{}` doesn't exist. PlayerDump won't work properly",
229 whereField, tableStruct.TableName);
230 ABORT();
231 return;
232 }
233
234 tableStruct.WhereFieldName = whereField;
235}
std::string WhereFieldName
Definition: PlayerDump.cpp:159

References ABORT, ASSERT, FindColumnByName(), LOG_FATAL, TableStruct::TableFields, TableStruct::TableName, and TableStruct::WhereFieldName.

Referenced by PlayerDump::InitializeTables().

◆ RegisterNewGuid()

template<typename T , template< class, class, class... > class MapType, class... Rest>
T RegisterNewGuid ( oldGuid,
MapType< T, T, Rest... > &  guidMap,
guidOffset 
)
inline
494{
495 auto itr = guidMap.find(oldGuid);
496 if (itr != guidMap.end())
497 return itr->second;
498
499 T newguid = guidOffset + T(guidMap.size());
500 guidMap.emplace(oldGuid, newguid);
501 return newguid;
502}

Referenced by ChangeGuid().

◆ StringsEqualCaseInsensitive()

bool StringsEqualCaseInsensitive ( std::string const &  left,
std::string const &  right 
)
inline
169{
170 std::string upperLeftString = left;
171 bool leftResult = Utf8ToUpperOnlyLatin(upperLeftString);
172 ASSERT(leftResult);
173
174 std::string upperRightString = right;
175 bool rightResult = Utf8ToUpperOnlyLatin(upperRightString);
176 ASSERT(rightResult);
177
178 return upperLeftString == upperRightString;
179}
bool Utf8ToUpperOnlyLatin(std::string &utf8String)
Definition: Util.cpp:527

References ASSERT, and Utf8ToUpperOnlyLatin().

◆ ValidateFields()

bool ValidateFields ( TableStruct const &  ts,
std::string const &  str,
size_t  lineNumber 
)
inline
430{
431 std::string::size_type s = str.find("` VALUES (");
432 if (s != std::string::npos) // old dump format (no column names)
433 return true;
434
435 // new format has insert with columns, need validation else we risk executing an invalid query
436 s = str.find("` (`");
437 if (s == std::string::npos)
438 {
439 LOG_ERROR("misc", "LoadPlayerDump: (line {}) dump format not recognized.", lineNumber);
440 return false;
441 }
442 s += 4;
443
444 std::string::size_type valPos = str.find("VALUES ('");
445 std::string::size_type e = str.find('`', s);
446 if (e == std::string::npos || valPos == std::string::npos)
447 {
448 LOG_ERROR("misc", "LoadPlayerDump: (line {}) unexpected end of line", lineNumber);
449 return false;
450 }
451
452 do
453 {
454 std::string column = str.substr(s, e - s);
455 int32 columnIndex = GetColumnIndexByName(ts, column);
456 if (columnIndex == -1)
457 {
458 LOG_ERROR("misc", "LoadPlayerDump: (line {}) unknown column name `{}` for table `{}`, aborting due to incompatible DB structure.", lineNumber, column, ts.TableName);
459 return false;
460 }
461
462 // length of "`, `"
463 s = e + 4;
464 e = str.find('`', s);
465 } while (e < valPos);
466
467 return true;
468}
#define LOG_ERROR(filterType__,...)
Definition: Log.h:157

References GetColumnIndexByName(), LOG_ERROR, and TableStruct::TableName.

Referenced by PlayerDumpReader::LoadDump().

Variable Documentation

◆ BaseTables

BaseTable const BaseTables[]
Initial value:
=
{
{ "character_pet", "id", "owner", GUID_TYPE_PET },
{ "mail", "id", "receiver", GUID_TYPE_MAIL },
{ "item_instance", "guid", "owner_guid", GUID_TYPE_ITEM },
{ "character_equipmentsets", "setguid", "guid", GUID_TYPE_EQUIPMENT_SET }
}

Referenced by PlayerDump::InitializeTables(), and PlayerDumpWriter::PopulateGuids().

◆ CharacterTables

◆ DUMP_TABLE_COUNT

uint32 const DUMP_TABLE_COUNT = std::extent<decltype(DumpTables)>::value

◆ DumpTables