QueryResult_AutoPtr DatabaseMysql::Query(const char *sql) { MYSQL_RES *result = NULL; MYSQL_FIELD *fields = NULL; uint64 rowCount = 0; uint32 fieldCount = 0; if (!_Query(sql, &result, &fields, &rowCount, &fieldCount)) return QueryResult_AutoPtr(NULL); QueryResultMysql *queryResult = new QueryResultMysql(result, fields, rowCount, fieldCount); queryResult->NextRow(); return QueryResult_AutoPtr(queryResult); }
QueryResult_AutoPtr Database::PQuery(const char *format,...) { if (!format) return QueryResult_AutoPtr(NULL); va_list ap; char szQuery [MAX_QUERY_LEN]; va_start(ap, format); int res = vsnprintf( szQuery, MAX_QUERY_LEN, format, ap ); va_end(ap); if (res==-1) { sLog.outError("SQL Query truncated (and not execute) for format: %s",format); return QueryResult_AutoPtr(NULL); } return Query(szQuery); }
QueryResult_AutoPtr MySQLConnection::Query(const char* sql) { if (!sql) return QueryResult_AutoPtr(NULL); MYSQL_RES *result = NULL; MYSQL_FIELD *fields = NULL; uint64 rowCount = 0; uint32 fieldCount = 0; if (!_Query(sql, &result, &fields, &rowCount, &fieldCount)) return QueryResult_AutoPtr(NULL); QueryResult *queryResult = new QueryResult(result, fields, rowCount, fieldCount); queryResult->NextRow(); return QueryResult_AutoPtr(queryResult); }
QueryResult_AutoPtr DatabaseWorkerPool::PQuery(const char* sql, ...) { if (!sql) return QueryResult_AutoPtr(NULL); va_list ap; char szQuery[MAX_QUERY_LEN]; va_start(ap, sql); int res = vsnprintf(szQuery, MAX_QUERY_LEN, sql, ap); va_end(ap); return Query(szQuery); }
QueryResult_AutoPtr SQLQueryHolder::GetResult(size_t index) { if (index < m_queries.size()) { /// the query strings are freed on the first GetResult or in the destructor if (m_queries[index].first != NULL) { free((void*)(const_cast<char*>(m_queries[index].first))); m_queries[index].first = NULL; } /// when you get a result aways remember to delete it! return m_queries[index].second; } else return QueryResult_AutoPtr(NULL); }
bool SQLQueryHolder::SetQuery(size_t index, const char *sql) { if (m_queries.size() <= index) { sLog.outError("Query index (%u) out of range (size: %u) for query: %s", index, (uint32)m_queries.size(), sql); return false; } if (m_queries[index].first != NULL) { sLog.outError("Attempt assign query to holder index (%u) where other query stored (Old: [%s] New: [%s])", index, m_queries[index].first, sql); return false; } /// not executed yet, just stored (it's not called a holder for nothing) m_queries[index] = SQLResultPair(strdup(sql), QueryResult_AutoPtr(NULL)); return true; }
DumpReturn PlayerDumpReader::LoadDump(const std::string& file, uint32 account, std::string name, uint32 guid) { uint32 charcount = accmgr.GetCharactersCount(account); if (charcount >= 10) return DUMP_TOO_MANY_CHARS; FILE *fin = fopen(file.c_str(), "r"); if (!fin) return DUMP_FILE_OPEN_ERROR; QueryResult_AutoPtr result = QueryResult_AutoPtr(NULL); char newguid[20], chraccount[20], newpetid[20], currpetid[20], lastpetid[20]; // make sure the same guid doesn't already exist and is safe to use bool incHighest = true; if (guid != 0 && guid < objmgr.m_hiCharGuid) { result = CharacterDatabase.PQuery("SELECT 1 FROM characters WHERE guid = '%d'", guid); if (result) guid = objmgr.m_hiCharGuid; // use first free if exists else incHighest = false; } else guid = objmgr.m_hiCharGuid; // normalize the name if specified and check if it exists if (!normalizePlayerName(name)) name = ""; if (ObjectMgr::CheckPlayerName(name,true) == CHAR_NAME_SUCCESS) { CharacterDatabase.escape_string(name); // for safe, we use name only for sql quearies anyway result = CharacterDatabase.PQuery("SELECT 1 FROM characters WHERE name = '%s'", name.c_str()); if (result) name = ""; // use the one from the dump } else name = ""; // name encoded or empty snprintf(newguid, 20, "%d", guid); snprintf(chraccount, 20, "%d", account); snprintf(newpetid, 20, "%d", objmgr.GeneratePetNumber()); snprintf(lastpetid, 20, "%s", ""); std::map<uint32,uint32> items; std::map<uint32,uint32> mails; char buf[32000] = ""; typedef std::map<uint32, uint32> PetIds; // old->new petid relation typedef PetIds::value_type PetIdsPair; PetIds petids; CharacterDatabase.BeginTransaction(); while (!feof(fin)) { if (!fgets(buf, 32000, fin)) { if (feof(fin)) break; ROLLBACK(DUMP_FILE_BROKEN); } std::string line; line.assign(buf); // skip empty strings size_t nw_pos = line.find_first_not_of(" \t\n\r\7"); if (nw_pos == std::string::npos) continue; // skip logfile-side dump start notice, the important notes and dump end notices if ((line.substr(nw_pos,16) == "== START DUMP ==") || (line.substr(nw_pos,15) == "IMPORTANT NOTE:") || (line.substr(nw_pos,14) == "== END DUMP ==")) continue; // add required_ check /* if (line.substr(nw_pos,41) == "UPDATE character_db_version SET required_") { if (!CharacterDatabase.Execute(line.c_str())) ROLLBACK(DUMP_FILE_BROKEN); continue; } */ // determine table name and load type std::string tn = gettablename(line); if (tn.empty()) { sLog.outError("LoadPlayerDump: Can't extract table name from line: '%s'!", line.c_str()); ROLLBACK(DUMP_FILE_BROKEN); } DumpTableType type; uint8 i; for (i = 0; i < DUMP_TABLE_COUNT; ++i) { if (tn == dumpTables[i].name) { type = dumpTables[i].type; break; } } if (i == DUMP_TABLE_COUNT) { sLog.outError("LoadPlayerDump: Unknown table: '%s'!", tn.c_str()); ROLLBACK(DUMP_FILE_BROKEN); } // change the data to server values switch(type) { case DTT_CHAR_TABLE: if (!changenth(line, 1, newguid)) // character_*.guid update ROLLBACK(DUMP_FILE_BROKEN); break; case DTT_CHARACTER: { if (!changenth(line, 1, newguid)) // characters.guid update ROLLBACK(DUMP_FILE_BROKEN); if (!changenth(line, 2, chraccount)) // characters.account update ROLLBACK(DUMP_FILE_BROKEN); if (name == "") { // check if the original name already exists name = getnth(line, 3); CharacterDatabase.escape_string(name); result = CharacterDatabase.PQuery("SELECT 1 FROM characters WHERE name = '%s'", name.c_str()); if (result) { if (!changenth(line, 37, "1")) // characters.at_login set to "rename on login" ROLLBACK(DUMP_FILE_BROKEN); } } else if (!changenth(line, 3, name.c_str())) // characters.name ROLLBACK(DUMP_FILE_BROKEN); const char null[5] = "NULL"; if (!changenth(line, 68, null)) // characters.deleteInfos_Account ROLLBACK(DUMP_FILE_BROKEN); if (!changenth(line, 69, null)) // characters.deleteInfos_Name ROLLBACK(DUMP_FILE_BROKEN); if (!changenth(line, 70, null)) // characters.deleteDate ROLLBACK(DUMP_FILE_BROKEN); break; } case DTT_INVENTORY: { if (!changenth(line, 1, newguid)) // character_inventory.guid update ROLLBACK(DUMP_FILE_BROKEN); if (!changeGuid(line, 2, items, objmgr.m_hiItemGuid, true)) ROLLBACK(DUMP_FILE_BROKEN); // character_inventory.bag update if (!changeGuid(line, 4, items, objmgr.m_hiItemGuid)) ROLLBACK(DUMP_FILE_BROKEN); // character_inventory.item update break; } case DTT_ITEM: { // item, owner, data field:item, owner guid if (!changeGuid(line, 1, items, objmgr.m_hiItemGuid)) ROLLBACK(DUMP_FILE_BROKEN); // item_instance.guid update if (!changenth(line, 2, newguid)) // item_instance.owner_guid update ROLLBACK(DUMP_FILE_BROKEN); break; } case DTT_ITEM_GIFT: { if (!changenth(line, 1, newguid)) // character_gifts.guid update ROLLBACK(DUMP_FILE_BROKEN); if (!changeGuid(line, 2, items, objmgr.m_hiItemGuid)) ROLLBACK(DUMP_FILE_BROKEN); // character_gifts.item_guid update break; } case DTT_PET: { //store a map of old pet id to new inserted pet id for use by type 5 tables snprintf(currpetid, 20, "%s", getnth(line, 1).c_str()); if (strlen(lastpetid) == 0) snprintf(lastpetid, 20, "%s", currpetid); if (strcmp(lastpetid,currpetid) != 0) { snprintf(newpetid, 20, "%d", objmgr.GeneratePetNumber()); snprintf(lastpetid, 20, "%s", currpetid); } std::map<uint32, uint32> :: const_iterator petids_iter = petids.find(atoi(currpetid)); if (petids_iter == petids.end()) { petids.insert(PetIdsPair(atoi(currpetid), atoi(newpetid))); } if (!changenth(line, 1, newpetid)) // character_pet.id update ROLLBACK(DUMP_FILE_BROKEN); if (!changenth(line, 3, newguid)) // character_pet.owner update ROLLBACK(DUMP_FILE_BROKEN); break; } case DTT_PET_TABLE: // pet_aura, pet_spell, pet_spell_cooldown { snprintf(currpetid, 20, "%s", getnth(line, 1).c_str()); // lookup currpetid and match to new inserted pet id std::map<uint32, uint32> :: const_iterator petids_iter = petids.find(atoi(currpetid)); if (petids_iter == petids.end()) // couldn't find new inserted id ROLLBACK(DUMP_FILE_BROKEN); snprintf(newpetid, 20, "%d", petids_iter->second); if (!changenth(line, 1, newpetid)) ROLLBACK(DUMP_FILE_BROKEN); break; } case DTT_MAIL: // mail { if (!changeGuid(line, 1, mails, objmgr.m_mailid)) ROLLBACK(DUMP_FILE_BROKEN); // mail.id update if (!changenth(line, 6, newguid)) // mail.receiver update ROLLBACK(DUMP_FILE_BROKEN); break; } case DTT_MAIL_ITEM: // mail_items { if (!changeGuid(line, 1, mails, objmgr.m_mailid)) ROLLBACK(DUMP_FILE_BROKEN); // mail_items.id if (!changeGuid(line, 2, items, objmgr.m_hiItemGuid)) ROLLBACK(DUMP_FILE_BROKEN); // mail_items.item_guid if (!changenth(line, 4, newguid)) // mail_items.receiver ROLLBACK(DUMP_FILE_BROKEN); break; } default: sLog.outError("Unknown dump table type: %u",type); break; } fixNULLfields(line); if (!CharacterDatabase.Execute(line.c_str())) ROLLBACK(DUMP_FILE_BROKEN); } CharacterDatabase.CommitTransaction(); objmgr.m_hiItemGuid += items.size(); objmgr.m_mailid += mails.size(); if (incHighest) ++objmgr.m_hiCharGuid; fclose(fin); return DUMP_SUCCESS; }
DumpReturn PlayerDumpReader::LoadDump(const std::string& file, uint32 account, std::string name, uint32 guid) { // check character count { QueryResult_AutoPtr result = CharacterDatabase.PQuery("SELECT COUNT(guid) FROM characters WHERE account = '%d'", account); uint8 charcount = 0; if (result) { Field *fields=result->Fetch(); charcount = fields[0].GetUInt8(); if (charcount >= 10) return DUMP_TOO_MANY_CHARS; } } FILE *fin = fopen(file.c_str(), "r"); if (!fin) return DUMP_FILE_OPEN_ERROR; QueryResult_AutoPtr result = QueryResult_AutoPtr(NULL); char newguid[20], chraccount[20], newpetid[20], currpetid[20], lastpetid[20]; // make sure the same guid doesn't already exist and is safe to use bool incHighest = true; if (guid != 0 && guid < sObjectMgr.m_hiCharGuid) { result = CharacterDatabase.PQuery("SELECT 1 FROM characters WHERE guid = '%d'", guid); if (result) guid = sObjectMgr.m_hiCharGuid; // use first free if exists else incHighest = false; } else guid = sObjectMgr.m_hiCharGuid; // normalize the name if specified and check if it exists if (!normalizePlayerName(name)) name = ""; if (ObjectMgr::CheckPlayerName(name,true) == CHAR_NAME_SUCCESS) { CharacterDatabase.escape_string(name); // for safe, we use name only for sql quearies anyway result = CharacterDatabase.PQuery("SELECT 1 FROM characters WHERE name = '%s'", name.c_str()); if (result) name = ""; // use the one from the dump } else name = ""; // name encoded or empty snprintf(newguid, 20, "%d", guid); snprintf(chraccount, 20, "%d", account); snprintf(newpetid, 20, "%d", sObjectMgr.GeneratePetNumber()); snprintf(lastpetid, 20, "%s", ""); std::map<uint32,uint32> items; std::map<uint32,uint32> mails; std::map<uint32,uint32> itemTexts; char buf[32000] = ""; typedef std::map<uint32, uint32> PetIds; // old->new petid relation typedef PetIds::value_type PetIdsPair; PetIds petids; CharacterDatabase.BeginTransaction(); while(!feof(fin)) { if (!fgets(buf, 32000, fin)) { if (feof(fin)) break; ROLLBACK(DUMP_FILE_BROKEN); } std::string line; line.assign(buf); // skip empty strings size_t nw_pos = line.find_first_not_of(" \t\n\r\7"); if (nw_pos==std::string::npos) continue; // skip NOTE if (line.substr(nw_pos,15)=="IMPORTANT NOTE:") continue; // add required_ check /* if (line.substr(nw_pos,41)=="UPDATE character_db_version SET required_") { if (!CharacterDatabase.Execute(line.c_str())) ROLLBACK(DUMP_FILE_BROKEN); continue; } */ // determine table name and load type std::string tn = gettablename(line); if (tn.empty()) { sLog.outError("LoadPlayerDump: Can't extract table name from line: '%s'!", line.c_str()); ROLLBACK(DUMP_FILE_BROKEN); } DumpTableType type; uint8 i; for (i = 0; i < DUMP_TABLE_COUNT; ++i) { if (tn == dumpTables[i].name) { type = dumpTables[i].type; break; } } if (i == DUMP_TABLE_COUNT) { sLog.outError("LoadPlayerDump: Unknown table: '%s'!", tn.c_str()); ROLLBACK(DUMP_FILE_BROKEN); } // change the data to server values switch (type) { case DTT_CHAR_TABLE: if (!changenth(line, 1, newguid)) ROLLBACK(DUMP_FILE_BROKEN); break; case DTT_CHARACTER: // character t. { if (!changenth(line, 1, newguid)) ROLLBACK(DUMP_FILE_BROKEN); // guid, data field:guid, items if (!changenth(line, 2, chraccount)) ROLLBACK(DUMP_FILE_BROKEN); std::string vals = getnth(line, 3); if (!changetoknth(vals, OBJECT_FIELD_GUID+1, newguid)) ROLLBACK(DUMP_FILE_BROKEN); for (uint16 field = PLAYER_FIELD_INV_SLOT_HEAD; field < PLAYER_FARSIGHT; field++) if (!changetokGuid(vals, field+1, items, sObjectMgr.m_hiItemGuid, true)) ROLLBACK(DUMP_FILE_BROKEN); if (!changenth(line, 3, vals.c_str())) ROLLBACK(DUMP_FILE_BROKEN); if (name == "") { // check if the original name already exists name = getnth(line, 4); CharacterDatabase.escape_string(name); result = CharacterDatabase.PQuery("SELECT 1 FROM characters WHERE name = '%s'", name.c_str()); if (result) { if (!changenth(line, 37, "1")) // rename on login: `at_login` field 37 in raw field list ROLLBACK(DUMP_FILE_BROKEN); } } else if (!changenth(line, 4, name.c_str())) ROLLBACK(DUMP_FILE_BROKEN); break; } case DTT_INVENTORY: // character_inventory t. { if (!changenth(line, 1, newguid)) ROLLBACK(DUMP_FILE_BROKEN); // bag, item if (!changeGuid(line, 2, items, sObjectMgr.m_hiItemGuid, true)) ROLLBACK(DUMP_FILE_BROKEN); if (!changeGuid(line, 4, items, sObjectMgr.m_hiItemGuid)) ROLLBACK(DUMP_FILE_BROKEN); break; } case DTT_ITEM: // item_instance t. { // item, owner, data field:item, owner guid if (!changeGuid(line, 1, items, sObjectMgr.m_hiItemGuid)) ROLLBACK(DUMP_FILE_BROKEN); if (!changenth(line, 2, newguid)) ROLLBACK(DUMP_FILE_BROKEN); std::string vals = getnth(line,3); if (!changetokGuid(vals, OBJECT_FIELD_GUID+1, items, sObjectMgr.m_hiItemGuid)) ROLLBACK(DUMP_FILE_BROKEN); if (!changetoknth(vals, ITEM_FIELD_OWNER+1, newguid)) ROLLBACK(DUMP_FILE_BROKEN); if (!changetokGuid(vals, ITEM_FIELD_ITEM_TEXT_ID+1, itemTexts, sObjectMgr.m_ItemTextId,true)) ROLLBACK(DUMP_FILE_BROKEN); if (!changenth(line, 3, vals.c_str())) ROLLBACK(DUMP_FILE_BROKEN); break; } case DTT_ITEM_GIFT: // character_gift { // guid,item_guid, if (!changenth(line, 1, newguid)) ROLLBACK(DUMP_FILE_BROKEN); if (!changeGuid(line, 2, items, sObjectMgr.m_hiItemGuid)) ROLLBACK(DUMP_FILE_BROKEN); break; } case DTT_PET: // character_pet t { //store a map of old pet id to new inserted pet id for use by type 5 tables snprintf(currpetid, 20, "%s", getnth(line, 1).c_str()); if (strlen(lastpetid)==0) snprintf(lastpetid, 20, "%s", currpetid); if (strcmp(lastpetid,currpetid)!=0) { snprintf(newpetid, 20, "%d", sObjectMgr.GeneratePetNumber()); snprintf(lastpetid, 20, "%s", currpetid); } std::map<uint32, uint32> :: const_iterator petids_iter = petids.find(atoi(currpetid)); if (petids_iter == petids.end()) { petids.insert(PetIdsPair(atoi(currpetid), atoi(newpetid))); } // item, entry, owner, ... if (!changenth(line, 1, newpetid)) ROLLBACK(DUMP_FILE_BROKEN); if (!changenth(line, 3, newguid)) ROLLBACK(DUMP_FILE_BROKEN); break; } case DTT_PET_TABLE: // pet_aura, pet_spell, pet_spell_cooldown t { snprintf(currpetid, 20, "%s", getnth(line, 1).c_str()); // lookup currpetid and match to new inserted pet id std::map<uint32, uint32> :: const_iterator petids_iter = petids.find(atoi(currpetid)); if (petids_iter == petids.end()) // couldn't find new inserted id ROLLBACK(DUMP_FILE_BROKEN); snprintf(newpetid, 20, "%d", petids_iter->second); if (!changenth(line, 1, newpetid)) ROLLBACK(DUMP_FILE_BROKEN); break; } case DTT_MAIL: // mail { // id,messageType,stationery,mailtemplate,sender,receiver,subject,itemText if (!changeGuid(line, 1, mails, sObjectMgr.m_mailid)) ROLLBACK(DUMP_FILE_BROKEN); if (!changenth(line, 6, newguid)) ROLLBACK(DUMP_FILE_BROKEN); if (!changeGuid(line, 8, itemTexts, sObjectMgr.m_ItemTextId)) ROLLBACK(DUMP_FILE_BROKEN); break; } case DTT_MAIL_ITEM: // mail_items { // mail_id,item_guid,item_template,receiver if (!changeGuid(line, 1, mails, sObjectMgr.m_mailid)) ROLLBACK(DUMP_FILE_BROKEN); if (!changeGuid(line, 2, items, sObjectMgr.m_hiItemGuid)) ROLLBACK(DUMP_FILE_BROKEN); if (!changenth(line, 4, newguid)) ROLLBACK(DUMP_FILE_BROKEN); break; } case DTT_ITEM_TEXT: // item_text { // id if (!changeGuid(line, 1, itemTexts, sObjectMgr.m_ItemTextId)) ROLLBACK(DUMP_FILE_BROKEN); // add it to cache uint32 id= atoi(getnth(line,1).c_str()); std::string text = getnth(line,2); sObjectMgr.AddItemText(id,text); break; } default: sLog.outError("Unknown dump table type: %u",type); break; } if (!CharacterDatabase.Execute(line.c_str())) ROLLBACK(DUMP_FILE_BROKEN); } CharacterDatabase.CommitTransaction(); sObjectMgr.m_hiItemGuid += items.size(); sObjectMgr.m_mailid += mails.size(); sObjectMgr.m_ItemTextId += itemTexts.size(); if (incHighest) ++sObjectMgr.m_hiCharGuid; fclose(fin); return DUMP_SUCCESS; }