[10026] PDump code fixes and cleanups
[getmangos.git] / src / game / PlayerDump.cpp
blobae46b64d5cf36492239ce42f23fbbdd3adb973a4
1 /*
2 * Copyright (C) 2005-2010 MaNGOS <http://getmangos.com/>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 #include "Common.h"
20 #include "PlayerDump.h"
21 #include "Database/DatabaseEnv.h"
22 #include "Database/SQLStorage.h"
23 #include "UpdateFields.h"
24 #include "ObjectMgr.h"
25 #include "AccountMgr.h"
27 // Character Dump tables
28 struct DumpTable
30 char const* name;
31 DumpTableType type;
33 // helpers
34 bool isValid() const { return name != NULL; }
37 static DumpTable dumpTables[] =
39 { "characters", DTT_CHARACTER }, // -> guid, must be first for name check
40 { "character_account_data", DTT_CHAR_TABLE },
41 { "character_achievement", DTT_CHAR_TABLE },
42 { "character_achievement_progress", DTT_CHAR_TABLE },
43 { "character_action", DTT_CHAR_TABLE },
44 { "character_aura", DTT_CHAR_TABLE },
45 { "character_declinedname", DTT_CHAR_NAME_TABLE },
46 { "character_equipmentsets", DTT_EQSET_TABLE},
47 { "character_glyphs", DTT_CHAR_TABLE },
48 { "character_homebind", DTT_CHAR_TABLE },
49 { "character_inventory", DTT_INVENTORY }, // -> item guids
50 { "character_queststatus", DTT_CHAR_TABLE },
51 { "character_pet", DTT_PET }, // -> pet number
52 { "character_pet_declinedname", DTT_PET_DECL }, // <- pet number
53 { "character_reputation", DTT_CHAR_TABLE },
54 { "character_skills", DTT_CHAR_TABLE },
55 { "character_spell", DTT_CHAR_TABLE },
56 { "character_spell_cooldown", DTT_CHAR_TABLE },
57 { "character_talent", DTT_CHAR_TABLE },
58 { "character_ticket", DTT_CHAR_TABLE },
59 { "mail", DTT_MAIL }, // -> mail guids
60 { "mail_items", DTT_MAIL_ITEM }, // -> item guids <- mail guids
61 { "pet_aura", DTT_PET_TABLE }, // <- pet number
62 { "pet_spell", DTT_PET_TABLE }, // <- pet number
63 { "pet_spell_cooldown", DTT_PET_TABLE }, // <- pet number
64 { "character_gifts", DTT_ITEM_GIFT }, // <- item guids
65 { "item_instance", DTT_ITEM }, // <- item guids
66 { NULL, DTT_CHAR_TABLE }, // end marker
69 // Low level functions
70 static bool findtoknth(std::string &str, int n, std::string::size_type &s, std::string::size_type &e)
72 int i; s = e = 0;
73 std::string::size_type size = str.size();
74 for(i = 1; s < size && i < n; s++) if(str[s] == ' ') ++i;
75 if (i < n)
76 return false;
78 e = str.find(' ', s);
80 return e != std::string::npos;
83 std::string gettoknth(std::string &str, int n)
85 std::string::size_type s = 0, e = 0;
86 if (!findtoknth(str, n, s, e))
87 return "";
89 return str.substr(s, e-s);
92 bool findnth(std::string &str, int n, std::string::size_type &s, std::string::size_type &e)
94 s = str.find("VALUES ('")+9;
95 if (s == std::string::npos)
96 return false;
100 e = str.find("'",s);
101 if (e == std::string::npos)
102 return false;
103 } while(str[e-1] == '\\');
105 for(int i = 1; i < n; ++i)
109 s = e+4;
110 e = str.find("'",s);
111 if (e == std::string::npos)
112 return false;
113 } while (str[e-1] == '\\');
115 return true;
118 std::string gettablename(std::string &str)
120 std::string::size_type s = 13;
121 std::string::size_type e = str.find(_TABLE_SIM_, s);
122 if (e == std::string::npos)
123 return "";
125 return str.substr(s, e-s);
128 bool changenth(std::string &str, int n, const char *with, bool insert = false, bool nonzero = false)
130 std::string::size_type s, e;
131 if (!findnth(str,n,s,e))
132 return false;
134 if (nonzero && str.substr(s,e-s) == "0")
135 return true; // not an error
136 if (!insert)
137 str.replace(s,e-s, with);
138 else
139 str.insert(s, with);
141 return true;
144 std::string getnth(std::string &str, int n)
146 std::string::size_type s, e;
147 if (!findnth(str,n,s,e))
148 return "";
150 return str.substr(s, e-s);
153 bool changetoknth(std::string &str, int n, const char *with, bool insert = false, bool nonzero = false)
155 std::string::size_type s = 0, e = 0;
156 if (!findtoknth(str, n, s, e))
157 return false;
158 if (nonzero && str.substr(s,e-s) == "0")
159 return true; // not an error
160 if (!insert)
161 str.replace(s, e-s, with);
162 else
163 str.insert(s, with);
165 return true;
168 uint32 registerNewGuid(uint32 oldGuid, std::map<uint32, uint32> &guidMap, uint32 hiGuid)
170 std::map<uint32, uint32>::const_iterator itr = guidMap.find(oldGuid);
171 if (itr != guidMap.end())
172 return itr->second;
174 uint32 newguid = hiGuid + guidMap.size();
175 guidMap[oldGuid] = newguid;
176 return newguid;
179 bool changeGuid(std::string &str, int n, std::map<uint32, uint32> &guidMap, uint32 hiGuid, bool nonzero = false)
181 char chritem[20];
182 uint32 oldGuid = atoi(getnth(str, n).c_str());
183 if (nonzero && oldGuid == 0)
184 return true; // not an error
186 uint32 newGuid = registerNewGuid(oldGuid, guidMap, hiGuid);
187 snprintf(chritem, 20, "%d", newGuid);
189 return changenth(str, n, chritem, false, nonzero);
192 bool changetokGuid(std::string &str, int n, std::map<uint32, uint32> &guidMap, uint32 hiGuid, bool nonzero = false)
194 char chritem[20];
195 uint32 oldGuid = atoi(gettoknth(str, n).c_str());
196 if (nonzero && oldGuid == 0)
197 return true; // not an error
199 uint32 newGuid = registerNewGuid(oldGuid, guidMap, hiGuid);
200 snprintf(chritem, 20, "%d", newGuid);
202 return changetoknth(str, n, chritem, false, nonzero);
205 std::string CreateDumpString(char const* tableName, QueryResult *result)
207 if (!tableName || !result)
208 return "";
210 std::ostringstream ss;
211 ss << "INSERT INTO "<< _TABLE_SIM_ << tableName << _TABLE_SIM_ << " VALUES (";
212 Field *fields = result->Fetch();
213 for(uint32 i = 0; i < result->GetFieldCount(); ++i)
215 if (i != 0)
216 ss << ", ";
218 if (fields[i].IsNULL())
219 ss << "NULL";
220 else
222 std::string s = fields[i].GetCppString();
223 CharacterDatabase.escape_string(s);
225 ss << "'" << s << "'";
228 ss << ");";
229 return ss.str();
232 std::string PlayerDumpWriter::GenerateWhereStr(char const* field, uint32 guid)
234 std::ostringstream wherestr;
235 wherestr << field << " = '" << guid << "'";
236 return wherestr.str();
239 std::string PlayerDumpWriter::GenerateWhereStr(char const* field, GUIDs const& guids, GUIDs::const_iterator& itr)
241 std::ostringstream wherestr;
242 wherestr << field << " IN ('";
243 for(; itr != guids.end(); ++itr)
245 wherestr << *itr;
247 if (wherestr.str().size() > MAX_QUERY_LEN - 50) // near to max query
249 ++itr;
250 break;
253 GUIDs::const_iterator itr2 = itr;
254 if (++itr2 != guids.end())
255 wherestr << "','";
257 wherestr << "')";
258 return wherestr.str();
261 void StoreGUID(QueryResult *result,uint32 field,std::set<uint32>& guids)
263 Field* fields = result->Fetch();
264 uint32 guid = fields[field].GetUInt32();
265 if (guid)
266 guids.insert(guid);
269 void StoreGUID(QueryResult *result,uint32 data,uint32 field, std::set<uint32>& guids)
271 Field* fields = result->Fetch();
272 std::string dataStr = fields[data].GetCppString();
273 uint32 guid = atoi(gettoknth(dataStr, field).c_str());
274 if (guid)
275 guids.insert(guid);
278 // Writing - High-level functions
279 void PlayerDumpWriter::DumpTableContent(std::string& dump, uint32 guid, char const*tableFrom, char const*tableTo, DumpTableType type)
281 GUIDs const* guids = NULL;
282 char const* fieldname = NULL;
284 switch ( type )
286 case DTT_ITEM: fieldname = "guid"; guids = &items; break;
287 case DTT_ITEM_GIFT: fieldname = "item_guid"; guids = &items; break;
288 case DTT_PET: fieldname = "owner"; break;
289 case DTT_PET_TABLE: fieldname = "guid"; guids = &pets; break;
290 case DTT_PET_DECL: fieldname = "id"; break;
291 case DTT_MAIL: fieldname = "receiver"; break;
292 case DTT_MAIL_ITEM: fieldname = "mail_id"; guids = &mails; break;
293 default: fieldname = "guid"; break;
296 // for guid set stop if set is empty
297 if (guids && guids->empty())
298 return; // nothing to do
300 // setup for guids case start position
301 GUIDs::const_iterator guids_itr;
302 if (guids)
303 guids_itr = guids->begin();
307 std::string wherestr;
309 if (guids) // set case, get next guids string
310 wherestr = GenerateWhereStr(fieldname,*guids,guids_itr);
311 else // not set case, get single guid string
312 wherestr = GenerateWhereStr(fieldname,guid);
314 QueryResult *result = CharacterDatabase.PQuery("SELECT * FROM %s WHERE %s", tableFrom, wherestr.c_str());
315 if (!result)
316 return;
320 // collect guids
321 switch ( type )
323 case DTT_INVENTORY:
324 StoreGUID(result,3,items); break; // item guid collection (character_inventory.item)
325 case DTT_PET:
326 StoreGUID(result,0,pets); break; // pet petnumber collection (character_pet.id)
327 case DTT_MAIL:
328 StoreGUID(result,0,mails); // mail id collection (mail.id)
329 case DTT_MAIL_ITEM:
330 StoreGUID(result,1,items); break; // item guid collection (mail_items.item_guid)
331 default: break;
334 dump += CreateDumpString(tableTo, result);
335 dump += "\n";
337 while (result->NextRow());
339 delete result;
341 while(guids && guids_itr != guids->end()); // not set case iterate single time, set case iterate for all guids
344 std::string PlayerDumpWriter::GetDump(uint32 guid)
346 std::string dump;
348 dump += "IMPORTANT NOTE: This sql queries not created for apply directly, use '.pdump load' command in console or client chat instead.\n";
349 dump += "IMPORTANT NOTE: NOT APPLY ITS DIRECTLY to character DB or you will DAMAGE and CORRUPT character DB\n\n";
351 // revision check guard
352 QueryNamedResult* result = CharacterDatabase.QueryNamed("SELECT * FROM character_db_version LIMIT 1");
353 if (result)
355 QueryFieldNames const& namesMap = result->GetFieldNames();
356 std::string reqName;
357 for(QueryFieldNames::const_iterator itr = namesMap.begin(); itr != namesMap.end(); ++itr)
359 if (itr->substr(0,9)=="required_")
361 reqName = *itr;
362 break;
366 if (!reqName.empty())
368 // this will fail at wrong character DB version
369 dump += "UPDATE character_db_version SET "+reqName+" = 1 WHERE FALSE;\n\n";
371 else
372 sLog.outError("Table 'character_db_version' not have revision guard field, revision guard query not added to pdump.");
374 delete result;
376 else
377 sLog.outError("Character DB not have 'character_db_version' table, revision guard query not added to pdump.");
379 for(DumpTable* itr = &dumpTables[0]; itr->isValid(); ++itr)
380 DumpTableContent(dump, guid, itr->name, itr->name, itr->type);
382 // TODO: Add instance/group..
383 // TODO: Add a dump level option to skip some non-important tables
385 return dump;
388 DumpReturn PlayerDumpWriter::WriteDump(const std::string& file, uint32 guid)
390 FILE *fout = fopen(file.c_str(), "w");
391 if (!fout)
392 return DUMP_FILE_OPEN_ERROR;
394 std::string dump = GetDump(guid);
396 fprintf(fout,"%s\n",dump.c_str());
397 fclose(fout);
398 return DUMP_SUCCESS;
401 // Reading - High-level functions
402 #define ROLLBACK(DR) {CharacterDatabase.RollbackTransaction(); fclose(fin); return (DR);}
404 DumpReturn PlayerDumpReader::LoadDump(const std::string& file, uint32 account, std::string name, uint32 guid)
406 bool nameInvalidated = false; // set when name changed or will requested changed at next login
408 // check character count
409 uint32 charcount = sAccountMgr.GetCharactersCount(account);
410 if (charcount >= 10)
411 return DUMP_TOO_MANY_CHARS;
413 FILE *fin = fopen(file.c_str(), "r");
414 if (!fin)
415 return DUMP_FILE_OPEN_ERROR;
417 QueryResult * result = NULL;
418 char newguid[20], chraccount[20], newpetid[20], currpetid[20], lastpetid[20];
420 // make sure the same guid doesn't already exist and is safe to use
421 bool incHighest = true;
422 if (guid != 0 && guid < sObjectMgr.m_CharGuids.GetNextAfterMaxUsed())
424 result = CharacterDatabase.PQuery("SELECT * FROM characters WHERE guid = '%d'", guid);
425 if (result)
427 guid = sObjectMgr.m_CharGuids.GetNextAfterMaxUsed();
428 delete result;
430 else incHighest = false;
432 else
433 guid = sObjectMgr.m_CharGuids.GetNextAfterMaxUsed();
435 // normalize the name if specified and check if it exists
436 if (!normalizePlayerName(name))
437 name = "";
439 if (ObjectMgr::CheckPlayerName(name,true) == CHAR_NAME_SUCCESS)
441 CharacterDatabase.escape_string(name); // for safe, we use name only for sql quearies anyway
442 result = CharacterDatabase.PQuery("SELECT * FROM characters WHERE name = '%s'", name.c_str());
443 if (result)
445 name = ""; // use the one from the dump
446 delete result;
449 else
450 name = "";
452 // name encoded or empty
454 snprintf(newguid, 20, "%d", guid);
455 snprintf(chraccount, 20, "%d", account);
456 snprintf(newpetid, 20, "%d", sObjectMgr.GeneratePetNumber());
457 snprintf(lastpetid, 20, "%s", "");
459 std::map<uint32,uint32> items;
460 std::map<uint32,uint32> mails;
461 std::map<uint32,uint32> eqsets;
462 char buf[32000] = "";
464 typedef std::map<uint32, uint32> PetIds; // old->new petid relation
465 typedef PetIds::value_type PetIdsPair;
466 PetIds petids;
468 CharacterDatabase.BeginTransaction();
469 while(!feof(fin))
471 if (!fgets(buf, 32000, fin))
473 if(feof(fin)) break;
474 ROLLBACK(DUMP_FILE_BROKEN);
477 std::string line; line.assign(buf);
479 // skip empty strings
480 size_t nw_pos = line.find_first_not_of(" \t\n\r\7");
481 if (nw_pos==std::string::npos)
482 continue;
484 // skip NOTE
485 if (line.substr(nw_pos,15)=="IMPORTANT NOTE:")
486 continue;
488 // add required_ check
489 if (line.substr(nw_pos,41)=="UPDATE character_db_version SET required_")
491 if (!CharacterDatabase.Execute(line.c_str()))
492 ROLLBACK(DUMP_FILE_BROKEN);
494 continue;
497 // determine table name and load type
498 std::string tn = gettablename(line);
499 if (tn.empty())
501 sLog.outError("LoadPlayerDump: Can't extract table name from line: '%s'!", line.c_str());
502 ROLLBACK(DUMP_FILE_BROKEN);
505 DumpTableType type = DTT_CHARACTER; //Fixed: Using uninitialized memory 'type'
506 DumpTable* dTable = &dumpTables[0];
507 for(; dTable->isValid(); ++dTable)
509 if (tn == dTable->name)
511 type = dTable->type;
512 break;
516 if (!dTable->isValid())
518 sLog.outError("LoadPlayerDump: Unknown table: '%s'!", tn.c_str());
519 ROLLBACK(DUMP_FILE_BROKEN);
522 bool execute_ok = true; // false, if need skip soem query
524 // change the data to server values
525 switch(type)
527 case DTT_CHAR_TABLE:
528 if (!changenth(line, 1, newguid)) // character_*.guid update
529 ROLLBACK(DUMP_FILE_BROKEN);
530 break;
532 case DTT_CHAR_NAME_TABLE:
533 if (nameInvalidated) // ignore declined names if name will changed in some way
535 execute_ok = false;
536 break;
539 if (!changenth(line, 1, newguid)) // character_*.guid update
540 ROLLBACK(DUMP_FILE_BROKEN);
541 break;
543 case DTT_CHARACTER:
545 if (!changenth(line, 1, newguid)) // characters.guid update
546 ROLLBACK(DUMP_FILE_BROKEN);
548 if (!changenth(line, 2, chraccount)) // characters.account update
549 ROLLBACK(DUMP_FILE_BROKEN);
551 if (name == "")
553 // check if the original name already exists
554 name = getnth(line, 3); // characters.name
555 CharacterDatabase.escape_string(name);
557 result = CharacterDatabase.PQuery("SELECT * FROM characters WHERE name = '%s'", name.c_str());
558 if (result)
560 delete result;
562 if (!changenth(line, 36, "1")) // characters.at_login set to "rename on login"
563 ROLLBACK(DUMP_FILE_BROKEN);
565 nameInvalidated = true;
568 else
570 if (!changenth(line, 3, name.c_str())) // characters.name update
571 ROLLBACK(DUMP_FILE_BROKEN);
573 nameInvalidated = true;
576 break;
578 case DTT_INVENTORY:
580 if (!changenth(line, 1, newguid)) // character_inventory.guid update
581 ROLLBACK(DUMP_FILE_BROKEN);
583 if (!changeGuid(line, 2, items, sObjectMgr.m_ItemGuids.GetNextAfterMaxUsed(), true))
584 ROLLBACK(DUMP_FILE_BROKEN); // character_inventory.bag update
585 if (!changeGuid(line, 4, items, sObjectMgr.m_ItemGuids.GetNextAfterMaxUsed()))
586 ROLLBACK(DUMP_FILE_BROKEN); // character_inventory.item update
587 break;
589 case DTT_ITEM:
591 // item, owner, data field:item, owner guid
592 if (!changeGuid(line, 1, items, sObjectMgr.m_ItemGuids.GetNextAfterMaxUsed()))
593 ROLLBACK(DUMP_FILE_BROKEN); // item_instance.guid update
594 if (!changenth(line, 2, newguid)) // item_instance.owner_guid update
595 ROLLBACK(DUMP_FILE_BROKEN);
596 std::string vals = getnth(line,3); // item_instance.data get
597 if (!changetokGuid(vals, OBJECT_FIELD_GUID+1, items, sObjectMgr.m_ItemGuids.GetNextAfterMaxUsed()))
598 ROLLBACK(DUMP_FILE_BROKEN); // item_instance.data.OBJECT_FIELD_GUID update
599 if (!changetoknth(vals, ITEM_FIELD_OWNER+1, newguid))
600 ROLLBACK(DUMP_FILE_BROKEN); // item_instance.data.ITEM_FIELD_OWNER update
601 if (!changenth(line, 3, vals.c_str())) // item_instance.data update
602 ROLLBACK(DUMP_FILE_BROKEN);
603 break;
605 case DTT_ITEM_GIFT:
607 if (!changenth(line, 1, newguid)) // character_gifts.guid update
608 ROLLBACK(DUMP_FILE_BROKEN);
609 if (!changeGuid(line, 2, items, sObjectMgr.m_ItemGuids.GetNextAfterMaxUsed()))
610 ROLLBACK(DUMP_FILE_BROKEN); // character_gifts.item_guid update
611 break;
613 case DTT_PET:
615 //store a map of old pet id to new inserted pet id for use by type 5 tables
616 snprintf(currpetid, 20, "%s", getnth(line, 1).c_str());
617 if (strlen(lastpetid)==0)
618 snprintf(lastpetid, 20, "%s", currpetid);
620 if (strcmp(lastpetid,currpetid)!=0)
622 snprintf(newpetid, 20, "%d", sObjectMgr.GeneratePetNumber());
623 snprintf(lastpetid, 20, "%s", currpetid);
626 std::map<uint32, uint32> :: const_iterator petids_iter = petids.find(atoi(currpetid));
628 if (petids_iter == petids.end())
630 petids.insert(PetIdsPair(atoi(currpetid), atoi(newpetid)));
633 if (!changenth(line, 1, newpetid)) // character_pet.id update
634 ROLLBACK(DUMP_FILE_BROKEN);
635 if (!changenth(line, 3, newguid)) // character_pet.owner update
636 ROLLBACK(DUMP_FILE_BROKEN);
638 break;
640 case DTT_PET_TABLE: // pet_aura, pet_spell, pet_spell_cooldown
642 snprintf(currpetid, 20, "%s", getnth(line, 1).c_str());
644 // lookup currpetid and match to new inserted pet id
645 std::map<uint32, uint32> :: const_iterator petids_iter = petids.find(atoi(currpetid));
646 if (petids_iter == petids.end()) // couldn't find new inserted id
647 ROLLBACK(DUMP_FILE_BROKEN);
649 snprintf(newpetid, 20, "%d", petids_iter->second);
651 if (!changenth(line, 1, newpetid)) // pet_*.guid -> petid in fact
652 ROLLBACK(DUMP_FILE_BROKEN);
654 break;
656 case DTT_PET_DECL: // character_pet_declinedname
658 snprintf(currpetid, 20, "%s", getnth(line, 1).c_str());
660 // lookup currpetid and match to new inserted pet id
661 std::map<uint32, uint32> :: const_iterator petids_iter = petids.find(atoi(currpetid));
662 if (petids_iter == petids.end()) // couldn't find new inserted id
663 ROLLBACK(DUMP_FILE_BROKEN);
665 snprintf(newpetid, 20, "%d", petids_iter->second);
667 if (!changenth(line, 1, newpetid)) // character_pet_declinedname.id
668 ROLLBACK(DUMP_FILE_BROKEN);
670 if (!changenth(line, 2, newguid)) // character_pet_declinedname.owner update
671 ROLLBACK(DUMP_FILE_BROKEN);
673 break;
675 case DTT_MAIL: // mail
677 if (!changeGuid(line, 1, mails, sObjectMgr.m_MailIds.GetNextAfterMaxUsed()))
678 ROLLBACK(DUMP_FILE_BROKEN); // mail.id update
679 if (!changenth(line, 6, newguid)) // mail.receiver update
680 ROLLBACK(DUMP_FILE_BROKEN);
681 break;
683 case DTT_MAIL_ITEM: // mail_items
685 if (!changeGuid(line, 1, mails, sObjectMgr.m_MailIds.GetNextAfterMaxUsed()))
686 ROLLBACK(DUMP_FILE_BROKEN); // mail_items.id
687 if (!changeGuid(line, 2, items, sObjectMgr.m_ItemGuids.GetNextAfterMaxUsed()))
688 ROLLBACK(DUMP_FILE_BROKEN); // mail_items.item_guid
689 if (!changenth(line, 4, newguid)) // mail_items.receiver
690 ROLLBACK(DUMP_FILE_BROKEN);
691 break;
693 case DTT_EQSET_TABLE:
694 if (!changenth(line, 1, newguid)) // character_equipmentsets.guid update
695 ROLLBACK(DUMP_FILE_BROKEN);
696 if (!changeGuid(line, 2, eqsets, sObjectMgr.m_EquipmentSetIds.GetNextAfterMaxUsed()))
697 ROLLBACK(DUMP_FILE_BROKEN); // character_equipmentsets.setguid
698 for(int i = 0; i < 19; ++i) // character_equipmentsets.item0..item18
699 if(!changeGuid(line, 6+i, items, sObjectMgr.m_ItemGuids.GetNextAfterMaxUsed()))
700 ROLLBACK(DUMP_FILE_BROKEN);
701 break;
703 default:
704 sLog.outError("Unknown dump table type: %u",type);
705 break;
708 if (execute_ok && !CharacterDatabase.Execute(line.c_str()))
709 ROLLBACK(DUMP_FILE_BROKEN);
712 CharacterDatabase.CommitTransaction();
714 //FIXME: current code with post-updating guids not safe for future per-map threads
715 sObjectMgr.m_ItemGuids.Set(sObjectMgr.m_ItemGuids.GetNextAfterMaxUsed() + items.size());
716 sObjectMgr.m_MailIds.Set(sObjectMgr.m_MailIds.GetNextAfterMaxUsed() + mails.size());
717 sObjectMgr.m_EquipmentSetIds.Set(sObjectMgr.m_EquipmentSetIds.GetNextAfterMaxUsed() + eqsets.size());
719 if (incHighest)
720 sObjectMgr.m_CharGuids.Set(sObjectMgr.m_CharGuids.GetNextAfterMaxUsed()+1);
722 fclose(fin);
724 return DUMP_SUCCESS;