103 {
"character_pet_declinedname",
DTT_PET },
134 std::ostringstream oss;
171 std::string upperLeftString = left;
175 std::string upperRightString = right;
179 return upperLeftString == upperRightString;
184 return std::find_if(tableStruct.TableFields.begin(), tableStruct.TableFields.end(), [columnName](
TableField const& tableField) ->
bool
186 return StringsEqualCaseInsensitive(tableField.FieldName, columnName);
204 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",
210 if (itr->IsDependentField)
212 TC_LOG_FATAL(
"server.loading",
"Attempt to mark column `{}` in table `{}` as dependent column but already marked! please check your code.",
218 itr->IsDependentField =
true;
219 itr->FieldGuidType = dependentType;
227 if (whereFieldItr == tableStruct.
TableFields.end())
229 TC_LOG_FATAL(
"server.loading",
"Column name `{}` set as 'WHERE' column for table `{}` doesn't exist. PlayerDump won't work properly",
242 return StringsEqualCaseInsensitive(tableStruct.TableName, baseTable.TableName);
248 ASSERT(columnItr != itr->TableFields.end());
251 ASSERT(columnItr != itr->TableFields.end());
270 std::string columnName = (*result)[0].GetString();
280 }
while (result->NextRow());
282 switch (dumpTable.Type)
356 TC_LOG_FATAL(
"server.loading",
"Wrong dump table type {}, probably added a new table type without updating code",
uint32(dumpTable.Type));
367 if (tableStruct.WhereFieldName.empty())
369 TC_LOG_FATAL(
"server.loading",
"Table `{}` defined in player dump doesn't have a WHERE query field", tableStruct.TableName);
383inline bool FindColumn(
TableStruct const& ts, std::string
const& str, std::string
const& column, std::string::size_type& s, std::string::size_type& e)
386 if (columnIndex == -1)
392 s = str.find(
"VALUES ('");
393 if (s == std::string::npos)
399 e = str.find(
'\'', s);
400 if (e == std::string::npos)
402 }
while (str[e - 1] ==
'\\');
404 for (
int32 i = 1; i < columnIndex; ++i)
410 e = str.find(
'\'', s);
411 if (e == std::string::npos)
413 }
while (str[e - 1] ==
'\\');
421 static std::string::size_type
const s = 13;
422 std::string::size_type e = str.find(
'`', s);
423 if (e == std::string::npos)
426 return str.substr(s, e - s);
431 std::string::size_type s = str.find(
"` VALUES (");
432 if (s != std::string::npos)
436 s = str.find(
"` (`");
437 if (s == std::string::npos)
439 TC_LOG_ERROR(
"misc",
"LoadPlayerDump: (line {}) dump format not recognized.", lineNumber);
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)
448 TC_LOG_ERROR(
"misc",
"LoadPlayerDump: (line {}) unexpected end of line", lineNumber);
454 std::string column = str.substr(s, e - s);
456 if (columnIndex == -1)
458 TC_LOG_ERROR(
"misc",
"LoadPlayerDump: (line {}) unknown column name `{}` for table `{}`, aborting due to incompatible DB structure.", lineNumber, column, ts.
TableName);
464 e = str.find(
'`', s);
465 }
while (e < valPos);
470inline bool ChangeColumn(
TableStruct const& ts, std::string& str, std::string
const& column, std::string
const& with,
bool allowZero =
false)
472 std::string::size_type s, e;
476 if (allowZero && str.substr(s, e - s) ==
"0")
479 str.replace(s, e - s, with);
485 std::string::size_type s, e;
489 return str.substr(s, e - s);
492template <
typename T,
template<
class,
class,
class...>
class MapType,
class... Rest>
495 auto itr = guidMap.find(oldGuid);
496 if (itr != guidMap.end())
499 T newguid = guidOffset + T(guidMap.size());
500 guidMap.emplace(oldGuid, newguid);
504template <
typename T,
template<
class,
class,
class...>
class MapType,
class... Rest>
505inline bool ChangeGuid(
TableStruct const& ts, std::string& str, std::string
const& column, MapType<T, T, Rest...>& guidMap, T guidOffset,
bool allowZero =
false)
507 T oldGuid = Trinity::StringTo<T>(
GetColumn(ts, str, column)).template value_or<T>(0);
508 if (allowZero && !oldGuid)
513 chritem = std::to_string(newGuid);
515 return ChangeColumn(ts, str, column, chritem, allowZero);
525 std::ostringstream ss;
526 ss <<
"INSERT INTO `" << tableStruct.
TableName <<
"` (";
529 ss <<
'`' << itr->FieldName <<
'`';
538 Field* fields = result->Fetch();
540 for (
uint32 i = 0; i < fieldSize;)
550 std::string s(cString);
552 ss <<
'\'' << s <<
'\'';
560 trans.
Append(ss.str().c_str());
561 }
while (result->NextRow());
566 std::ostringstream whereStr;
567 whereStr << field <<
" = '" << guid <<
'\'';
568 return whereStr.str();
571template <
typename T,
template<
class,
class...>
class SetType,
class... Rest>
572inline std::string
GenerateWhereStr(std::string
const& field, SetType<T, Rest...>
const& guidSet)
574 std::ostringstream whereStr;
575 whereStr << field <<
" IN ('";
576 for (
auto itr = guidSet.begin(); itr != guidSet.end();)
584 if (itr != guidSet.end())
588 return whereStr.str();
596 switch (baseTable.StoredType)
614 switch (baseTable.StoredType)
618 _items.insert(itemLowGuid);
622 _mails.insert(mailLowGuid);
626 _pets.insert(petLowGuid);
629 if (
uint64 eqSetId = (*result)[0].GetUInt64())
635 }
while (result->NextRow());
641 std::string whereStr;
642 switch (dumpTable.
Type)
676 switch (dumpTable.
Type)
685 if ((*result)[index].GetUInt32())
699 dump =
"IMPORTANT NOTE: THIS DUMPFILE IS MADE FOR USE WITH THE 'PDUMP' COMMAND ONLY - EITHER THROUGH INGAME CHAT OR ON CONSOLE!\n";
700 dump +=
"IMPORTANT NOTE: DO NOT apply it directly - it will irreversibly DAMAGE and CORRUPT your database! You have been warned!\n\n";
721 if (strchr(file.c_str(),
'\\') || strchr(file.c_str(),
'/'))
740 fprintf(fout.get(),
"%s", dump.c_str());
755 static std::string
const NullString(
"'NULL'");
756 size_t pos = line.find(NullString);
757 while (pos != std::string::npos)
759 line.replace(pos, NullString.length(),
"NULL");
760 pos = line.find(NullString);
770 std::string newguid, chraccount;
773 bool incHighest =
true;
774 if (guid && guid < sObjectMgr->GetGenerator<HighGuid::Player>().GetNextAfterMaxUsed())
803 newguid = std::to_string(guid);
804 chraccount = std::to_string(account);
806 std::map<ObjectGuid::LowType, ObjectGuid::LowType> items;
809 std::map<ObjectGuid::LowType, ObjectGuid::LowType> mails;
812 std::map<ObjectGuid::LowType, ObjectGuid::LowType> petIds;
815 std::map<uint64, uint64> equipmentSetIds;
826 size_t lineNumber = 0;
829 while (std::getline(input, line))
834 size_t nw_pos = line.find_first_not_of(
" \t\n\r\7");
835 if (nw_pos == std::string::npos)
839 static std::string
const SkippedLine =
"IMPORTANT NOTE:";
840 if (line.substr(nw_pos, SkippedLine.size()) == SkippedLine)
847 TC_LOG_ERROR(
"misc",
"LoadPlayerDump: (line {}) Can't extract table name!", lineNumber);
864 TC_LOG_ERROR(
"misc",
"LoadPlayerDump: (line {}) Unknown table: `{}`!", lineNumber, tn);
875 if (!field.IsDependentField)
878 switch (field.FieldGuidType)
881 if (!
ChangeColumn(ts, line, field.FieldName, chraccount))
889 if (!
ChangeGuid(ts, line, field.FieldName, petIds, petLowGuidOffset))
893 if (!
ChangeGuid(ts, line, field.FieldName, mails, mailLowGuidOffset))
897 if (!
ChangeGuid(ts, line, field.FieldName, items, itemLowGuidOffset,
true))
901 if (!
ChangeGuid(ts, line, field.FieldName, equipmentSetIds, equipmentSetGuidOffset))
906 static std::string
const NullString(
"NULL");
907 if (!
ChangeColumn(ts, line, field.FieldName, NullString))
919 race = Trinity::StringTo<uint8>(
GetColumn(ts, line,
"race")).value_or<
uint8>(0);
920 playerClass = Trinity::StringTo<uint8>(
GetColumn(ts, line,
"class")).value_or<
uint8>(0);
921 gender = Trinity::StringTo<uint8>(
GetColumn(ts, line,
"gender")).value_or<
uint8>(0);
922 level = Trinity::StringTo<uint8>(
GetColumn(ts, line,
"level")).value_or<
uint8>(0);
927 std::size_t maxCharsFromOriginalName =
MAX_PLAYER_NAME - guidPart.length();
929 name =
GetColumn(ts, line,
"name").substr(0, maxCharsFromOriginalName) + guidPart;
947 trans->Append(line.c_str());
950 if (input.fail() && !input.eof())
956 sCharacterCache->AddCharacterCacheEntry(ObjectGuid::Create<HighGuid::Player>(guid), account, name, gender, race, playerClass, level);
961 sObjectMgr->_equipmentSetGuid += equipmentSetIds.size();
966 sWorld->UpdateRealmCharCount(account);
973 std::istringstream input(dump);
974 return LoadDump(input, account, name, guid);
979 std::ifstream input(file);
982 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__,...)
#define TC_LOG_INFO(filterType__,...)
#define TC_LOG_FATAL(filterType__,...)
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)
static uint32 GetCharactersCount(uint32 accountId)
Class used to access individual fields of database query result.
char const * GetCString() const
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< ObjectGuid::LowType > _mails
std::set< ObjectGuid::LowType > _pets
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)
static void InitializeTables()
void setUInt32(uint8 index, uint32 value)
void setString(uint8 index, std::string const &value)
void Append(char const *sql)
char const * GetBuffer() const
@ CONFIG_PDUMP_NO_OVERWRITE
std::unordered_map< std::string, Player * > MapType
std::string StringFormat(FormatString< Args... > fmt, Args &&... args)
Default TC string format function.
void operator()(FILE *f) const
std::unordered_map< std::string, int32 > FieldIndices
std::vector< TableField > TableFields
std::string WhereFieldName