28#include <boost/algorithm/string/find.hpp>
113 {
"character_pet_declinedname",
DTT_PET },
120 {
"character_queststatus_objectives_criteria_progress",
DTT_CHAR_TABLE },
163 std::ostringstream oss;
201 std::string upperLeftString = left;
205 std::string upperRightString = right;
209 return upperLeftString == upperRightString;
214 return std::find_if(tableStruct.TableFields.begin(), tableStruct.TableFields.end(), [columnName](
TableField const& tableField) ->
bool
216 return StringsEqualCaseInsensitive(tableField.FieldName, columnName);
234 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",
240 if (itr->IsDependentField)
242 TC_LOG_FATAL(
"server.loading",
"Attempt to mark column `{}` in table `{}` as dependent column but already marked! please check your code.",
248 itr->IsDependentField =
true;
249 itr->FieldGuidType = dependentType;
257 if (whereFieldItr == tableStruct.
TableFields.end())
259 TC_LOG_FATAL(
"server.loading",
"Column name `{}` set as 'WHERE' column for table `{}` doesn't exist. PlayerDump won't work properly",
272 return StringsEqualCaseInsensitive(tableStruct.TableName, baseTable.TableName);
278 ASSERT(columnItr != itr->TableFields.end());
281 ASSERT(columnItr != itr->TableFields.end());
300 std::string columnName = (*result)[0].GetString();
301 std::string typeName = (*result)[1].GetString();
306 f.
IsBinaryField = !boost::ifind_first(typeName,
"binary").empty() || !boost::ifind_first(typeName,
"blob").empty();
312 }
while (result->NextRow());
314 switch (dumpTable.Type)
404 TC_LOG_FATAL(
"server.loading",
"Wrong dump table type {}, probably added a new table type without updating code",
uint32(dumpTable.Type));
415 if (tableStruct.WhereFieldName.empty())
417 TC_LOG_FATAL(
"server.loading",
"Table `{}` defined in player dump doesn't have a WHERE query field", tableStruct.TableName);
431inline bool FindColumn(
TableStruct const& ts, std::string
const& str, std::string
const& column, std::string::size_type& s, std::string::size_type& e)
434 if (columnIndex == -1)
440 s = str.find(
"VALUES (");
441 if (s == std::string::npos)
446 bool isQuoted = str[s] ==
'\'';
454 e = str.find(
'\'', e);
455 if (e == std::string::npos)
457 if (str[e - 1] ==
'\\')
459 if (e + 1 < str.length() && str[e + 1] ==
'\'')
468 e = str.find_first_of(
",)", e);
470 for (
int32 i = 1; i < columnIndex; ++i)
479 isQuoted = str[s] ==
'\'';
487 e = str.find(
'\'', e);
488 if (e == std::string::npos)
490 if (str[e - 1] ==
'\\')
492 if (e + 1 < str.length() && str[e + 1] ==
'\'')
498 }
while (str[e - 1] ==
'\\');
501 e = str.find_first_of(
",)", e);
510 static std::string::size_type
const s = 13;
511 std::string::size_type e = str.find(
'`', s);
512 if (e == std::string::npos)
515 return str.substr(s, e - s);
520 std::string::size_type s = str.find(
"` VALUES (");
521 if (s != std::string::npos)
525 s = str.find(
"` (`");
526 if (s == std::string::npos)
528 TC_LOG_ERROR(
"misc",
"LoadPlayerDump: (line {}) dump format not recognized.", lineNumber);
533 std::string::size_type valPos = str.find(
"VALUES ('");
534 std::string::size_type e = str.find(
'`', s);
535 if (e == std::string::npos || valPos == std::string::npos)
537 TC_LOG_ERROR(
"misc",
"LoadPlayerDump: (line {}) unexpected end of line", lineNumber);
543 std::string column = str.substr(s, e - s);
545 if (columnIndex == -1)
547 TC_LOG_ERROR(
"misc",
"LoadPlayerDump: (line {}) unknown column name `{}` for table `{}`, aborting due to incompatible DB structure.", lineNumber, column, ts.
TableName);
553 e = str.find(
'`', s);
554 }
while (e < valPos);
559inline bool ChangeColumn(
TableStruct const& ts, std::string& str, std::string
const& column, std::string
const& with,
bool allowZero =
false)
561 std::string::size_type s, e;
565 if (allowZero && str.substr(s, e - s) ==
"0")
568 str.replace(s, e - s, with);
574 std::string::size_type s, e;
578 return str.substr(s, e - s);
581template <
typename T,
template<
class,
class,
class...>
class MapType,
class... Rest>
584 auto itr = guidMap.find(oldGuid);
585 if (itr != guidMap.end())
588 T newguid = guidOffset + T(guidMap.size());
589 guidMap.emplace(oldGuid, newguid);
593template <
typename T,
template<
class,
class,
class...>
class MapType,
class... Rest>
594inline bool ChangeGuid(
TableStruct const& ts, std::string& str, std::string
const& column, MapType<T, T, Rest...>& guidMap, T guidOffset,
bool allowZero =
false)
596 T oldGuid = Trinity::StringTo<T>(
GetColumn(ts, str, column)).template value_or<T>(0);
597 if (allowZero && !oldGuid)
602 chritem = std::to_string(newGuid);
604 return ChangeColumn(ts, str, column, chritem, allowZero);
614 std::ostringstream ss;
615 ss <<
"INSERT INTO `" << tableStruct.
TableName <<
"` (";
618 ss <<
'`' << itr->FieldName <<
'`';
627 Field* fields = result->Fetch();
629 for (
uint32 i = 0; i < fieldSize;)
631 if (fields[i].IsNull())
637 std::string s(fields[i].GetString());
639 ss <<
'\'' << s <<
'\'';
643 std::vector<uint8> b(fields[i].GetBinary());
658 trans.
Append(ss.str().c_str());
659 }
while (result->NextRow());
664 std::ostringstream whereStr;
665 whereStr << field <<
" = '" << guid <<
'\'';
666 return whereStr.str();
669template <
typename T,
template<
class,
class...>
class SetType,
class... Rest>
670inline std::string
GenerateWhereStr(std::string
const& field, SetType<T, Rest...>
const& guidSet)
672 std::ostringstream whereStr;
673 whereStr << field <<
" IN ('";
674 for (
auto itr = guidSet.begin(); itr != guidSet.end();)
682 if (itr != guidSet.end())
686 return whereStr.str();
694 switch (baseTable.StoredType)
712 switch (baseTable.StoredType)
716 _items.insert(itemLowGuid);
719 if (
uint32 mailLowGuid = (*result)[0].GetUInt32())
720 _mails.insert(mailLowGuid);
723 if (
uint32 petLowGuid = (*result)[0].GetUInt32())
724 _pets.insert(petLowGuid);
727 if (
uint64 eqSetId = (*result)[0].GetUInt64())
733 }
while (result->NextRow());
739 std::string whereStr;
740 switch (dumpTable.
Type)
776 switch (dumpTable.
Type)
785 if ((*result)[index].GetUInt32())
799 dump =
"IMPORTANT NOTE: THIS DUMPFILE IS MADE FOR USE WITH THE 'PDUMP' COMMAND ONLY - EITHER THROUGH INGAME CHAT OR ON CONSOLE!\n";
800 dump +=
"IMPORTANT NOTE: DO NOT apply it directly - it will irreversibly DAMAGE and CORRUPT your database! You have been warned!\n\n";
821 if (strchr(file.c_str(),
'\\') || strchr(file.c_str(),
'/'))
840 fprintf(fout.get(),
"%s", dump.c_str());
855 static std::string
const NullString(
"'NULL'");
856 size_t pos = line.find(NullString);
857 while (pos != std::string::npos)
859 line.replace(pos, NullString.length(),
"NULL");
860 pos = line.find(NullString);
870 std::string newguid, chraccount;
873 bool incHighest =
true;
874 if (guid && guid < sObjectMgr->GetGenerator<HighGuid::Player>().GetNextAfterMaxUsed())
903 newguid = std::to_string(guid);
904 chraccount = std::to_string(account);
906 std::map<ObjectGuid::LowType, ObjectGuid::LowType> items;
909 std::map<uint64, uint64> mails;
912 std::map<uint32, uint32> petIds;
915 std::map<uint64, uint64> equipmentSetIds;
926 size_t lineNumber = 0;
929 while (std::getline(input, line))
934 size_t nw_pos = line.find_first_not_of(
" \t\n\r\7");
935 if (nw_pos == std::string::npos)
939 static std::string
const SkippedLine =
"IMPORTANT NOTE:";
940 if (line.substr(nw_pos, SkippedLine.size()) == SkippedLine)
947 TC_LOG_ERROR(
"misc",
"LoadPlayerDump: (line {}) Can't extract table name!", lineNumber);
964 TC_LOG_ERROR(
"misc",
"LoadPlayerDump: (line {}) Unknown table: `{}`!", lineNumber, tn);
1006 static std::string
const NullString(
"NULL");
1019 race = Trinity::StringTo<uint8>(
GetColumn(ts, line,
"race")).value_or<
uint8>(0);
1020 playerClass = Trinity::StringTo<uint8>(
GetColumn(ts, line,
"class")).value_or<
uint8>(0);
1021 gender = Trinity::StringTo<uint8>(
GetColumn(ts, line,
"gender")).value_or<
uint8>(0);
1022 level = Trinity::StringTo<uint8>(
GetColumn(ts, line,
"level")).value_or<
uint8>(0);
1027 std::size_t maxCharsFromOriginalName =
MAX_PLAYER_NAME - guidPart.length();
1029 name =
GetColumn(ts, line,
"name").substr(0, maxCharsFromOriginalName) + guidPart;
1047 trans->Append(line.c_str());
1050 if (input.fail() && !input.eof())
1056 sCharacterCache->AddCharacterCacheEntry(ObjectGuid::Create<HighGuid::Player>(guid), account, name, gender, race, playerClass, level,
false);
1061 sObjectMgr->_equipmentSetGuid += equipmentSetIds.size();
1066 sWorld->UpdateRealmCharCount(account);
1073 std::istringstream input(dump);
1074 return LoadDump(input, account, name, guid);
1079 std::ifstream input(file);
1082 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)
std::string ByteArrayToHexStr(Container const &c, bool reverse=false)
static uint32 GetCharactersCount(uint32 accountId)
Class used to access individual fields of database query result.
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(const uint8 index, const std::string &value)
void setUInt64(const uint8 index, const 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)
Default TC string format function.
void operator()(FILE *f) const
std::unordered_map< std::string, int32 > FieldIndices
std::vector< TableField > TableFields
std::string WhereFieldName