112 {
"character_pet_declinedname",
DTT_PET },
119 {
"character_queststatus_objectives_criteria_progress",
DTT_CHAR_TABLE },
162 std::ostringstream oss;
200 std::string upperLeftString = left;
204 std::string upperRightString = right;
208 return upperLeftString == upperRightString;
213 return std::find_if(tableStruct.TableFields.begin(), tableStruct.TableFields.end(), [columnName](
TableField const& tableField) ->
bool
215 return StringsEqualCaseInsensitive(tableField.FieldName, columnName);
233 TC_LOG_FATAL(
"server.loading",
"Column `{}` declared in table `{}` marked as dependent but doesn't exist, PlayerDump will not work properly, please update table definitions",
239 if (itr->IsDependentField)
241 TC_LOG_FATAL(
"server.loading",
"Attempt to mark column `{}` in table `{}` as dependent column but already marked! please check your code.",
247 itr->IsDependentField =
true;
248 itr->FieldGuidType = dependentType;
256 if (whereFieldItr == tableStruct.
TableFields.end())
258 TC_LOG_FATAL(
"server.loading",
"Column name `{}` set as 'WHERE' column for table `{}` doesn't exist. PlayerDump won't work properly",
271 return StringsEqualCaseInsensitive(tableStruct.TableName, baseTable.TableName);
277 ASSERT(columnItr != itr->TableFields.end());
280 ASSERT(columnItr != itr->TableFields.end());
299 std::string columnName = (*result)[0].GetString();
300 std::string typeName = (*result)[1].GetString();
311 }
while (result->NextRow());
313 switch (dumpTable.Type)
403 TC_LOG_FATAL(
"server.loading",
"Wrong dump table type {}, probably added a new table type without updating code",
uint32(dumpTable.Type));
414 if (tableStruct.WhereFieldName.empty())
416 TC_LOG_FATAL(
"server.loading",
"Table `{}` defined in player dump doesn't have a WHERE query field", tableStruct.TableName);
430inline bool FindColumn(
TableStruct const& ts, std::string
const& str, std::string
const& column, std::string::size_type& s, std::string::size_type& e)
433 if (columnIndex == -1)
439 s = str.find(
"VALUES (");
440 if (s == std::string::npos)
445 bool isQuoted = str[s] ==
'\'';
453 e = str.find(
'\'', e);
454 if (e == std::string::npos)
456 if (str[e - 1] ==
'\\')
458 if (e + 1 < str.length() && str[e + 1] ==
'\'')
467 e = str.find_first_of(
",)", e);
469 for (
int32 i = 1; i < columnIndex; ++i)
478 isQuoted = str[s] ==
'\'';
486 e = str.find(
'\'', e);
487 if (e == std::string::npos)
489 if (str[e - 1] ==
'\\')
491 if (e + 1 < str.length() && str[e + 1] ==
'\'')
497 }
while (str[e - 1] ==
'\\');
500 e = str.find_first_of(
",)", e);
509 static std::string::size_type
const s = 13;
510 std::string::size_type e = str.find(
'`', s);
511 if (e == std::string::npos)
514 return str.substr(s, e - s);
519 std::string::size_type s = str.find(
"` VALUES (");
520 if (s != std::string::npos)
524 s = str.find(
"` (`");
525 if (s == std::string::npos)
527 TC_LOG_ERROR(
"misc",
"LoadPlayerDump: (line {}) dump format not recognized.", lineNumber);
532 std::string::size_type valPos = str.find(
"VALUES ('");
533 std::string::size_type e = str.find(
'`', s);
534 if (e == std::string::npos || valPos == std::string::npos)
536 TC_LOG_ERROR(
"misc",
"LoadPlayerDump: (line {}) unexpected end of line", lineNumber);
542 std::string column = str.substr(s, e - s);
544 if (columnIndex == -1)
546 TC_LOG_ERROR(
"misc",
"LoadPlayerDump: (line {}) unknown column name `{}` for table `{}`, aborting due to incompatible DB structure.", lineNumber, column, ts.
TableName);
552 e = str.find(
'`', s);
553 }
while (e < valPos);
558inline bool ChangeColumn(
TableStruct const& ts, std::string& str, std::string
const& column, std::string
const& with,
bool allowZero =
false)
560 std::string::size_type s, e;
564 if (allowZero && str.substr(s, e - s) ==
"0")
567 str.replace(s, e - s, with);
573 std::string::size_type s, e;
577 return str.substr(s, e - s);
580template <
typename T,
template<
class,
class,
class...>
class MapType,
class... Rest>
583 auto itr = guidMap.find(oldGuid);
584 if (itr != guidMap.end())
587 T newguid = guidOffset + T(guidMap.size());
588 guidMap.emplace(oldGuid, newguid);
592template <
typename T,
template<
class,
class,
class...>
class MapType,
class... Rest>
593inline bool ChangeGuid(
TableStruct const& ts, std::string& str, std::string
const& column, MapType<T, T, Rest...>& guidMap, T guidOffset,
bool allowZero =
false)
595 T oldGuid = Trinity::StringTo<T>(
GetColumn(ts, str, column)).template value_or<T>(0);
596 if (allowZero && !oldGuid)
601 chritem = std::to_string(newGuid);
603 return ChangeColumn(ts, str, column, chritem, allowZero);
613 std::ostringstream ss;
614 ss <<
"INSERT INTO `" << tableStruct.
TableName <<
"` (";
617 ss <<
'`' << itr->FieldName <<
'`';
626 Field* fields = result->Fetch();
628 for (
uint32 i = 0; i < fieldSize;)
630 if (fields[i].IsNull())
636 std::string s(fields[i].GetString());
638 ss <<
'\'' << s <<
'\'';
657 trans.
Append(ss.str().c_str());
658 }
while (result->NextRow());
663 std::ostringstream whereStr;
664 whereStr << field <<
" = '" << guid <<
'\'';
665 return whereStr.str();
668template <
typename T,
template<
class,
class...>
class SetType,
class... Rest>
669inline std::string
GenerateWhereStr(std::string
const& field, SetType<T, Rest...>
const& guidSet)
671 std::ostringstream whereStr;
672 whereStr << field <<
" IN ('";
673 for (
auto itr = guidSet.begin(); itr != guidSet.end();)
681 if (itr != guidSet.end())
685 return whereStr.str();
693 switch (baseTable.StoredType)
711 switch (baseTable.StoredType)
715 _items.insert(itemLowGuid);
718 if (
uint32 mailLowGuid = (*result)[0].GetUInt32())
719 _mails.insert(mailLowGuid);
722 if (
uint32 petLowGuid = (*result)[0].GetUInt32())
723 _pets.insert(petLowGuid);
726 if (
uint64 eqSetId = (*result)[0].GetUInt64())
732 }
while (result->NextRow());
738 std::string whereStr;
739 switch (dumpTable.
Type)
775 switch (dumpTable.
Type)
784 if ((*result)[index].GetUInt32())
800 dump =
"IMPORTANT NOTE: THIS DUMPFILE IS MADE FOR USE WITH THE 'PDUMP' COMMAND ONLY - EITHER THROUGH INGAME CHAT OR ON CONSOLE!\n";
801 dump +=
"IMPORTANT NOTE: DO NOT apply it directly - it will irreversibly DAMAGE and CORRUPT your database! You have been warned!\n\n";
822 if (strchr(file.c_str(),
'\\') || strchr(file.c_str(),
'/'))
841 fprintf(fout.get(),
"%s", dump.c_str());
856 static std::string
const NullString(
"'NULL'");
857 size_t pos = line.find(NullString);
858 while (pos != std::string::npos)
860 line.replace(pos, NullString.length(),
"NULL");
861 pos = line.find(NullString);
871 std::string newguid, chraccount;
874 bool incHighest =
true;
875 if (guid && guid < sObjectMgr->GetGenerator<HighGuid::Player>().GetNextAfterMaxUsed())
904 newguid = std::to_string(guid);
905 chraccount = std::to_string(account);
907 std::map<ObjectGuid::LowType, ObjectGuid::LowType> items;
910 std::map<uint64, uint64> mails;
913 std::map<uint32, uint32> petIds;
916 std::map<uint64, uint64> equipmentSetIds;
927 size_t lineNumber = 0;
930 while (std::getline(input, line))
935 size_t nw_pos = line.find_first_not_of(
" \t\n\r\7");
936 if (nw_pos == std::string::npos)
940 static std::string
const SkippedLine =
"IMPORTANT NOTE:";
941 if (line.substr(nw_pos, SkippedLine.size()) == SkippedLine)
948 TC_LOG_ERROR(
"misc",
"LoadPlayerDump: (line {}) Can't extract table name!", lineNumber);
965 TC_LOG_ERROR(
"misc",
"LoadPlayerDump: (line {}) Unknown table: `{}`!", lineNumber, tn);
976 if (!field.IsDependentField)
979 switch (field.FieldGuidType)
982 if (!
ChangeColumn(ts, line, field.FieldName, chraccount))
990 if (!
ChangeGuid(ts, line, field.FieldName, petIds, petLowGuidOffset))
994 if (!
ChangeGuid(ts, line, field.FieldName, mails, mailLowGuidOffset))
998 if (!
ChangeGuid(ts, line, field.FieldName, items, itemLowGuidOffset,
true))
1002 if (!
ChangeGuid(ts, line, field.FieldName, equipmentSetIds, equipmentSetGuidOffset))
1007 static std::string
const NullString(
"NULL");
1008 if (!
ChangeColumn(ts, line, field.FieldName, NullString))
1020 race = Trinity::StringTo<uint8>(
GetColumn(ts, line,
"race")).value_or<
uint8>(0);
1021 playerClass = Trinity::StringTo<uint8>(
GetColumn(ts, line,
"class")).value_or<
uint8>(0);
1022 gender = Trinity::StringTo<uint8>(
GetColumn(ts, line,
"gender")).value_or<
uint8>(0);
1023 level = Trinity::StringTo<uint8>(
GetColumn(ts, line,
"level")).value_or<
uint8>(0);
1028 std::size_t maxCharsFromOriginalName =
MAX_PLAYER_NAME - guidPart.length();
1030 name =
GetColumn(ts, line,
"name").substr(0, maxCharsFromOriginalName) + guidPart;
1048 trans->Append(line.c_str());
1051 if (input.fail() && !input.eof())
1057 sCharacterCache->AddCharacterCacheEntry(ObjectGuid::Create<HighGuid::Player>(guid), account, name, gender, race, playerClass, level,
false);
1062 sObjectMgr->_equipmentSetGuid += equipmentSetIds.size();
1067 sWorld->UpdateRealmCharCount(account);
1074 std::istringstream input(dump);
1075 return LoadDump(input, account, name, guid);
1080 std::ifstream input(file);
1083 return LoadDump(input, account, name, guid);
SQLTransaction< CharacterDatabaseConnection > CharacterDatabaseTransaction
std::shared_ptr< ResultSet > QueryResult
std::shared_ptr< PreparedResultSet > PreparedQueryResult
DatabaseWorkerPool< CharacterDatabaseConnection > CharacterDatabase
Accessor to the character database.
#define TC_LOG_ERROR(filterType__, message__,...)
#define TC_LOG_FATAL(filterType__, message__,...)
#define TC_LOG_INFO(filterType__, message__,...)
bool normalizePlayerName(std::string &name)
void MarkDependentColumn(TableStruct &tableStruct, std::string const &columnName, GuidType dependentType)
std::string GetColumn(TableStruct const &ts, std::string &str, std::string const &column)
void AppendTableDump(StringTransaction &trans, TableStruct const &tableStruct, QueryResult result)
void AssertBaseTable(BaseTable const &baseTable)
bool ChangeGuid(TableStruct const &ts, std::string &str, std::string const &column, MapType< T, T, Rest... > &guidMap, T guidOffset, bool allowZero=false)
bool ChangeColumn(TableStruct const &ts, std::string &str, std::string const &column, std::string const &with, bool allowZero=false)
FileHandle GetFileHandle(char const *path, char const *mode)
uint32 const DUMP_TABLE_COUNT
@ GUID_TYPE_EQUIPMENT_SET
bool StringsEqualCaseInsensitive(std::string const &left, std::string const &right)
DumpTable const DumpTables[]
int32 GetColumnIndexByName(TableStruct const &tableStruct, std::string const &columnName)
T RegisterNewGuid(T oldGuid, MapType< T, T, Rest... > &guidMap, T guidOffset)
BaseTable const BaseTables[]
void MarkWhereField(TableStruct &tableStruct, std::string const &whereField)
void FixNULLfields(std::string &line)
std::unique_ptr< FILE, FileCloser > FileHandle
std::vector< TableStruct > CharacterTables
auto FindColumnByName(TableStruct &tableStruct, std::string const &columnName) -> decltype(tableStruct.TableFields.begin())
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)
std::string GenerateWhereStr(std::string const &field, ObjectGuid::LowType guid)
bool ValidateFields(TableStruct const &ts, std::string const &str, size_t lineNumber)
uint32 GetMSTimeDiffToNow(uint32 oldMSTime)
bool Utf8ToUpperOnlyLatin(std::string &utf8String)
bool StringContainsStringI(std::string_view haystack, std::string_view needle)
std::string ByteArrayToHexStr(Container const &c, bool reverse=false)
static uint32 GetCharactersCount(uint32 accountId)
Class used to access individual fields of database query result.
std::span< uint8 const > GetBinaryView() const noexcept
static ResponseCodes CheckPlayerName(std::string_view name, LocaleConstant locale, bool create=false)
DumpReturn LoadDump(std::istream &input, uint32 account, std::string name, ObjectGuid::LowType guid)
DumpReturn LoadDumpFromString(std::string const &dump, uint32 account, std::string name, ObjectGuid::LowType guid)
DumpReturn LoadDumpFromFile(std::string const &file, uint32 account, std::string name, ObjectGuid::LowType guid)
bool GetDump(ObjectGuid::LowType guid, std::string &dump)
std::set< uint64 > _itemSets
DumpReturn WriteDumpToString(std::string &dump, ObjectGuid::LowType guid)
std::set< ObjectGuid::LowType > _items
bool AppendTable(StringTransaction &trans, ObjectGuid::LowType guid, TableStruct const &tableStruct, DumpTable const &dumpTable)
DumpReturn WriteDumpToFile(std::string const &file, ObjectGuid::LowType guid)
void PopulateGuids(ObjectGuid::LowType guid)
std::set< uint32 > _mails
static void InitializeTables()
void setString(uint8 index, std::string &&value)
void setUInt64(uint8 index, uint64 value)
void Append(char const *sql)
char const * GetBuffer() const
@ CONFIG_CHARACTERS_PER_REALM
@ CONFIG_PDUMP_NO_OVERWRITE
std::unordered_map< std::string, Player * > MapType
std::string StringFormat(FormatString< Args... > fmt, Args &&... args) noexcept
Default TC string format function.
void operator()(FILE *f) const
std::unordered_map< std::string, int32 > FieldIndices
std::vector< TableField > TableFields
std::string WhereFieldName