diff options
author | Machiavelli <none@none> | 2010-08-21 03:19:25 +0200 |
---|---|---|
committer | Machiavelli <none@none> | 2010-08-21 03:19:25 +0200 |
commit | 994186f2672547761392c71ed15ded2a83e8c20d (patch) | |
tree | 53eec0c7571642b9490d2a664671cb216a730993 | |
parent | a7498d2f560e24b2ae3b4f6cc46ea2223a41e16f (diff) |
DB Layer:
- Make SQL Transactions actual objects used in code. (Thanks to Derex for the idea)
* Uncommitted transactions will be automatically rolled back and cleaned up using ACE_Refcounted_Auto_Ptr, so no need to call Rollback() in the code.
* Prevents recursive transactions and makes developers aware of transactions going on.
* Gets rid of unneccesary overhead iterating over a concurrent map.
- Some cleanups in affected code, including better usage of transaction control in AH / mail related code to prevent data loss.
*** Experimental, use at own risk, recommended to backup your DBs. ***
--HG--
branch : trunk
49 files changed, 863 insertions, 776 deletions
diff --git a/src/server/game/Accounts/AccountMgr.cpp b/src/server/game/Accounts/AccountMgr.cpp index 8a53daa8278..fac696546d1 100644 --- a/src/server/game/Accounts/AccountMgr.cpp +++ b/src/server/game/Accounts/AccountMgr.cpp @@ -27,8 +27,6 @@ #include "Util.h" #include "SHA1.h" -extern DatabaseType LoginDatabase; - AccountMgr::AccountMgr() {} @@ -86,13 +84,13 @@ AccountOpResult AccountMgr::DeleteAccount(uint32 accid) CharacterDatabase.PExecute("DELETE FROM character_tutorial WHERE account = '%u'",accid); CharacterDatabase.PExecute("DELETE FROM account_data WHERE account = '%u'",accid); - LoginDatabase.BeginTransaction(); + SQLTransaction trans = LoginDatabase.BeginTransaction(); - LoginDatabase.PExecute("DELETE FROM account WHERE id='%d'", accid); - LoginDatabase.PExecute("DELETE FROM account_access WHERE id ='%d'", accid); - LoginDatabase.PExecute("DELETE FROM realmcharacters WHERE acctid='%d'", accid); + trans->PAppend("DELETE FROM account WHERE id='%d'", accid); + trans->PAppend("DELETE FROM account_access WHERE id ='%d'", accid); + trans->PAppend("DELETE FROM realmcharacters WHERE acctid='%d'", accid); - LoginDatabase.CommitTransaction(); + LoginDatabase.CommitTransaction(trans); return AOR_OK; } diff --git a/src/server/game/Achievements/AchievementMgr.cpp b/src/server/game/Achievements/AchievementMgr.cpp index 13df36dbc96..58cd7f25140 100644 --- a/src/server/game/Achievements/AchievementMgr.cpp +++ b/src/server/game/Achievements/AchievementMgr.cpp @@ -440,13 +440,13 @@ void AchievementMgr::ResetAchievementCriteria(AchievementCriteriaTypes type, uin void AchievementMgr::DeleteFromDB(uint32 lowguid) { - CharacterDatabase.BeginTransaction (); - CharacterDatabase.PExecute("DELETE FROM character_achievement WHERE guid = %u",lowguid); - CharacterDatabase.PExecute("DELETE FROM character_achievement_progress WHERE guid = %u",lowguid); - CharacterDatabase.CommitTransaction (); + SQLTransaction trans = CharacterDatabase.BeginTransaction(); + trans->PAppend("DELETE FROM character_achievement WHERE guid = %u",lowguid); + trans->PAppend("DELETE FROM character_achievement_progress WHERE guid = %u",lowguid); + CharacterDatabase.CommitTransaction(trans); } -void AchievementMgr::SaveToDB() +void AchievementMgr::SaveToDB(SQLTransaction& trans) { if (!m_completedAchievements.empty()) { @@ -485,8 +485,8 @@ void AchievementMgr::SaveToDB() if (need_execute) { - CharacterDatabase.Execute(ssdel.str().c_str()); - CharacterDatabase.Execute(ssins.str().c_str()); + trans->Append(ssdel.str().c_str()); + trans->Append(ssins.str().c_str()); } } @@ -545,9 +545,9 @@ void AchievementMgr::SaveToDB() if (need_execute_del || need_execute_ins) { if (need_execute_del) - CharacterDatabase.Execute(ssdel.str().c_str()); + trans->Append(ssdel.str().c_str()); if (need_execute_ins) - CharacterDatabase.Execute(ssins.str().c_str()); + trans->Append(ssins.str().c_str()); } } } @@ -1953,16 +1953,18 @@ void AchievementMgr::CompletedAchievement(AchievementEntry const* achievement) MailDraft draft(subject, text); + SQLTransaction trans = CharacterDatabase.BeginTransaction(); if (item) { // save new item before send - item->SaveToDB(); // save for prevent lost at next mail load, if send fail then item will deleted + item->SaveToDB(trans); // save for prevent lost at next mail load, if send fail then item will deleted // item draft.AddItem(item); } - draft.SendMailTo(GetPlayer(), MailSender(MAIL_CREATURE, reward->sender)); + draft.SendMailTo(trans, GetPlayer(), MailSender(MAIL_CREATURE, reward->sender)); + CharacterDatabase.CommitTransaction(trans); } } diff --git a/src/server/game/Achievements/AchievementMgr.h b/src/server/game/Achievements/AchievementMgr.h index f0da91c2fa6..7c6d9f0b003 100644 --- a/src/server/game/Achievements/AchievementMgr.h +++ b/src/server/game/Achievements/AchievementMgr.h @@ -244,7 +244,7 @@ class AchievementMgr void Reset(); static void DeleteFromDB(uint32 lowguid); void LoadFromDB(QueryResult_AutoPtr achievementResult, QueryResult_AutoPtr criteriaResult); - void SaveToDB(); + void SaveToDB(SQLTransaction& trans); void ResetAchievementCriteria(AchievementCriteriaTypes type, uint32 miscvalue1 = 0, uint32 miscvalue2 = 0, bool evenIfCriteriaComplete = false); void UpdateAchievementCriteria(AchievementCriteriaTypes type, uint32 miscvalue1 = 0, uint32 miscvalue2 = 0, Unit *unit = NULL, uint32 time = 0); void CompletedAchievement(AchievementEntry const* entry); diff --git a/src/server/game/AuctionHouse/AuctionHouseMgr.cpp b/src/server/game/AuctionHouse/AuctionHouseMgr.cpp index 11918bff2ef..0c004d62726 100644 --- a/src/server/game/AuctionHouse/AuctionHouseMgr.cpp +++ b/src/server/game/AuctionHouse/AuctionHouseMgr.cpp @@ -88,7 +88,7 @@ uint32 AuctionHouseMgr::GetAuctionDeposit(AuctionHouseEntry const* entry, uint32 } //does not clear ram -void AuctionHouseMgr::SendAuctionWonMail(AuctionEntry *auction) +void AuctionHouseMgr::SendAuctionWonMail(AuctionEntry *auction, SQLTransaction& trans) { Item *pItem = GetAItem(auction->item_guidlow); if (!pItem) @@ -146,7 +146,7 @@ void AuctionHouseMgr::SendAuctionWonMail(AuctionEntry *auction) // set owner to bidder (to prevent delete item with sender char deleting) // owner in `data` will set at mail receive and item extracting - CharacterDatabase.PExecute("UPDATE item_instance SET owner_guid = '%u' WHERE guid='%u'",auction->bidder,pItem->GetGUIDLow()); + trans->PAppend("UPDATE item_instance SET owner_guid = '%u' WHERE guid='%u'",auction->bidder,pItem->GetGUIDLow()); if (bidder) { @@ -157,11 +157,11 @@ void AuctionHouseMgr::SendAuctionWonMail(AuctionEntry *auction) MailDraft(msgAuctionWonSubject.str(), msgAuctionWonBody.str()) .AddItem(pItem) - .SendMailTo(MailReceiver(bidder,auction->bidder), auction, MAIL_CHECK_MASK_COPIED); + .SendMailTo(trans, MailReceiver(bidder,auction->bidder), auction, MAIL_CHECK_MASK_COPIED); } } -void AuctionHouseMgr::SendAuctionSalePendingMail(AuctionEntry * auction) +void AuctionHouseMgr::SendAuctionSalePendingMail(AuctionEntry * auction, SQLTransaction& trans) { uint64 owner_guid = MAKE_NEW_GUID(auction->owner, 0, HIGHGUID_PLAYER); Player *owner = sObjectMgr.GetPlayer(owner_guid); @@ -186,12 +186,12 @@ void AuctionHouseMgr::SendAuctionSalePendingMail(AuctionEntry * auction) sLog.outDebug("AuctionSalePending body string : %s", msgAuctionSalePendingBody.str().c_str()); MailDraft(msgAuctionSalePendingSubject.str(), msgAuctionSalePendingBody.str()) - .SendMailTo(MailReceiver(owner,auction->owner), auction, MAIL_CHECK_MASK_COPIED); + .SendMailTo(trans, MailReceiver(owner,auction->owner), auction, MAIL_CHECK_MASK_COPIED); } } //call this method to send mail to auction owner, when auction is successful, it does not clear ram -void AuctionHouseMgr::SendAuctionSuccessfulMail(AuctionEntry * auction) +void AuctionHouseMgr::SendAuctionSuccessfulMail(AuctionEntry * auction, SQLTransaction& trans) { uint64 owner_guid = MAKE_NEW_GUID(auction->owner, 0, HIGHGUID_PLAYER); Player *owner = sObjectMgr.GetPlayer(owner_guid); @@ -224,12 +224,12 @@ void AuctionHouseMgr::SendAuctionSuccessfulMail(AuctionEntry * auction) } MailDraft(msgAuctionSuccessfulSubject.str(), auctionSuccessfulBody.str()) .AddMoney(profit) - .SendMailTo(MailReceiver(owner,auction->owner), auction, MAIL_CHECK_MASK_COPIED, sWorld.getConfig(CONFIG_MAIL_DELIVERY_DELAY)); + .SendMailTo(trans, MailReceiver(owner,auction->owner), auction, MAIL_CHECK_MASK_COPIED, sWorld.getConfig(CONFIG_MAIL_DELIVERY_DELAY)); } } //does not clear ram -void AuctionHouseMgr::SendAuctionExpiredMail(AuctionEntry * auction) +void AuctionHouseMgr::SendAuctionExpiredMail(AuctionEntry * auction, SQLTransaction& trans) { //return an item in auction to its owner by mail Item *pItem = GetAItem(auction->item_guidlow); @@ -250,10 +250,58 @@ void AuctionHouseMgr::SendAuctionExpiredMail(AuctionEntry * auction) MailDraft(subject.str(), "") // TODO: fix body .AddItem(pItem) - .SendMailTo(MailReceiver(owner,auction->owner), auction, MAIL_CHECK_MASK_COPIED); + .SendMailTo(trans, MailReceiver(owner,auction->owner), auction, MAIL_CHECK_MASK_COPIED, 0); } } +//this function sends mail to old bidder +void AuctionHouseMgr::SendAuctionOutbiddedMail(AuctionEntry *auction, uint32 newPrice, Player* newBidder, SQLTransaction& trans) +{ + uint64 oldBidder_guid = MAKE_NEW_GUID(auction->bidder,0, HIGHGUID_PLAYER); + Player *oldBidder = sObjectMgr.GetPlayer(oldBidder_guid); + + uint32 oldBidder_accId = 0; + if (!oldBidder) + oldBidder_accId = sObjectMgr.GetPlayerAccountIdByGUID(oldBidder_guid); + + // old bidder exist + if (oldBidder || oldBidder_accId) + { + std::ostringstream msgAuctionOutbiddedSubject; + msgAuctionOutbiddedSubject << auction->item_template << ":0:" << AUCTION_OUTBIDDED << ":0:0"; + + if (oldBidder && newBidder) + oldBidder->GetSession()->SendAuctionBidderNotification(auction->GetHouseId(), auction->Id, newBidder->GetGUID(), newPrice, auction->GetAuctionOutBid(), auction->item_template); + + MailDraft(msgAuctionOutbiddedSubject.str(), "") // TODO: fix body + .AddMoney(auction->bid) + .SendMailTo(trans, MailReceiver(oldBidder, auction->bidder), auction, MAIL_CHECK_MASK_COPIED); + } +} + +//this function sends mail, when auction is cancelled to old bidder +void AuctionHouseMgr::SendAuctionCancelledToBidderMail(AuctionEntry* auction, SQLTransaction& trans) +{ + uint64 bidder_guid = MAKE_NEW_GUID(auction->bidder, 0, HIGHGUID_PLAYER); + Player *bidder = sObjectMgr.GetPlayer(bidder_guid); + + uint32 bidder_accId = 0; + if (!bidder) + bidder_accId = sObjectMgr.GetPlayerAccountIdByGUID(bidder_guid); + + // bidder exist + if (bidder || bidder_accId) + { + std::ostringstream msgAuctionCancelledSubject; + msgAuctionCancelledSubject << auction->item_template << ":0:" << AUCTION_CANCELLED_TO_BIDDER << ":0:0"; + + MailDraft(msgAuctionCancelledSubject.str(), "") // TODO: fix body + .AddMoney(auction->bid) + .SendMailTo(trans, MailReceiver(bidder, auction->bidder), auction, MAIL_CHECK_MASK_COPIED); + } +} + + void AuctionHouseMgr::LoadAuctionItems() { // data needs to be at first place for Item::LoadFromDB @@ -342,6 +390,10 @@ void AuctionHouseMgr::LoadAuctions() barGoLink bar(AuctionCount); + //- TODO: Get rid of horrible design so we don't have to use transaction here to statisfy + //- function parameters. + SQLTransaction trans = CharacterDatabase.BeginTransaction(); + AuctionEntry *aItem; do @@ -366,7 +418,7 @@ void AuctionHouseMgr::LoadAuctions() CreatureData const* auctioneerData = sObjectMgr.GetCreatureData(aItem->auctioneer); if (!auctioneerData) { - aItem->DeleteFromDB(); + aItem->DeleteFromDB(trans); sLog.outError("Auction %u has not a existing auctioneer (GUID : %u)", aItem->Id, aItem->auctioneer); delete aItem; continue; @@ -375,7 +427,7 @@ void AuctionHouseMgr::LoadAuctions() CreatureInfo const* auctioneerInfo = sObjectMgr.GetCreatureTemplate(auctioneerData->id); if (!auctioneerInfo) { - aItem->DeleteFromDB(); + aItem->DeleteFromDB(trans); sLog.outError("Auction %u has not a existing auctioneer (GUID : %u Entry: %u)", aItem->Id, aItem->auctioneer,auctioneerData->id); delete aItem; continue; @@ -384,7 +436,7 @@ void AuctionHouseMgr::LoadAuctions() aItem->auctionHouseEntry = AuctionHouseMgr::GetAuctionHouseEntry(auctioneerInfo->faction_A); if (!aItem->auctionHouseEntry) { - aItem->DeleteFromDB(); + aItem->DeleteFromDB(trans); sLog.outError("Auction %u has auctioneer (GUID : %u Entry: %u) with wrong faction %u", aItem->Id, aItem->auctioneer,auctioneerData->id,auctioneerInfo->faction_A); delete aItem; @@ -395,7 +447,7 @@ void AuctionHouseMgr::LoadAuctions() // and item_template in fact (GetAItem will fail if problematic in result check in AuctionHouseMgr::LoadAuctionItems) if (!GetAItem(aItem->item_guidlow)) { - aItem->DeleteFromDB(); + aItem->DeleteFromDB(trans); sLog.outError("Auction %u has not a existing item : %u", aItem->Id, aItem->item_guidlow); delete aItem; continue; @@ -405,6 +457,8 @@ void AuctionHouseMgr::LoadAuctions() } while (result->NextRow()); + CharacterDatabase.CommitTransaction(trans); + sLog.outString(); sLog.outString(">> Loaded %u auctions", AuctionCount); } @@ -506,35 +560,20 @@ void AuctionHouseObject::Update() if (!result) return; - if (result->GetRowCount() == 0) - return; - - vector<uint32> expiredAuctions; - do { - uint32 tmpdata = result->Fetch()->GetUInt32(); - expiredAuctions.push_back(tmpdata); - } - while (result->NextRow()); - - while (!expiredAuctions.empty()) - { - vector<uint32>::iterator iter = expiredAuctions.begin(); - // from auctionhousehandler.cpp, creates auction pointer & player pointer - AuctionEntry* auction = GetAuction(*iter); - - // Erase the auction from the vector. - expiredAuctions.erase(iter); + AuctionEntry* auction = GetAuction(result->Fetch()->GetUInt32()); if (!auction) continue; + SQLTransaction trans = CharacterDatabase.BeginTransaction(); + ///- Either cancel the auction if there was no bidder if (auction->bidder == 0) { - sAuctionMgr.SendAuctionExpiredMail(auction); + sAuctionMgr.SendAuctionExpiredMail(auction, trans); sScriptMgr.OnAuctionExpire(this, auction); } ///- Or perform the transaction @@ -543,19 +582,21 @@ void AuctionHouseObject::Update() //we should send an "item sold" message if the seller is online //we send the item to the winner //we send the money to the seller - sAuctionMgr.SendAuctionSuccessfulMail(auction); - sAuctionMgr.SendAuctionWonMail(auction); + sAuctionMgr.SendAuctionSuccessfulMail(auction, trans); + sAuctionMgr.SendAuctionWonMail(auction, trans); sScriptMgr.OnAuctionSuccessful(this, auction); } - ///- In any case clear the auction - CharacterDatabase.BeginTransaction(); - auction->DeleteFromDB(); uint32 item_template = auction->item_template; - sAuctionMgr.RemoveAItem(auction->item_guidlow); + + ///- In any case clear the auction + auction->DeleteFromDB(trans); + CharacterDatabase.CommitTransaction(trans); + RemoveAuction(auction, item_template); - CharacterDatabase.CommitTransaction(); + sAuctionMgr.RemoveAItem(auction->item_guidlow); } + while (result->NextRow()); } void AuctionHouseObject::BuildListBidderItems(WorldPacket& data, Player* player, uint32& count, uint32& totalcount) @@ -746,16 +787,14 @@ uint32 AuctionEntry::GetAuctionOutBid() const return outbid; } -void AuctionEntry::DeleteFromDB() const +void AuctionEntry::DeleteFromDB(SQLTransaction& trans) const { - //No SQL injection (Id is integer) - CharacterDatabase.PExecute("DELETE FROM auctionhouse WHERE id = '%u'",Id); + trans->PAppend("DELETE FROM auctionhouse WHERE id = '%u'",Id); } -void AuctionEntry::SaveToDB() const +void AuctionEntry::SaveToDB(SQLTransaction& trans) const { - //No SQL injection (no strings) - CharacterDatabase.PExecute("INSERT INTO auctionhouse (id,auctioneerguid,itemguid,item_template,itemowner,buyoutprice,time,buyguid,lastbid,startbid,deposit) " + trans->PAppend("INSERT INTO auctionhouse (id,auctioneerguid,itemguid,item_template,itemowner,buyoutprice,time,buyguid,lastbid,startbid,deposit) " "VALUES ('%u', '%u', '%u', '%u', '%u', '%u', '" UI64FMTD "', '%u', '%u', '%u', '%u')", Id, auctioneer, item_guidlow, item_template, owner, buyout, (uint64)expire_time, bidder, bid, startbid, deposit); } diff --git a/src/server/game/AuctionHouse/AuctionHouseMgr.h b/src/server/game/AuctionHouse/AuctionHouseMgr.h index d81d68cb366..7fbee6e9132 100644 --- a/src/server/game/AuctionHouse/AuctionHouseMgr.h +++ b/src/server/game/AuctionHouse/AuctionHouseMgr.h @@ -66,8 +66,8 @@ struct AuctionEntry uint32 GetAuctionCut() const; uint32 GetAuctionOutBid() const; bool BuildAuctionInfo(WorldPacket & data) const; - void DeleteFromDB() const; - void SaveToDB() const; + void DeleteFromDB(SQLTransaction& trans) const; + void SaveToDB(SQLTransaction& trans) const; }; //this class is used as auctionhouse instance @@ -138,10 +138,13 @@ class AuctionHouseMgr } //auction messages - void SendAuctionWonMail(AuctionEntry * auction); - void SendAuctionSalePendingMail(AuctionEntry * auction); - void SendAuctionSuccessfulMail(AuctionEntry * auction); - void SendAuctionExpiredMail(AuctionEntry * auction); + void SendAuctionWonMail(AuctionEntry * auction, SQLTransaction& trans); + void SendAuctionSalePendingMail(AuctionEntry * auction, SQLTransaction& trans); + void SendAuctionSuccessfulMail(AuctionEntry * auction, SQLTransaction& trans); + void SendAuctionExpiredMail(AuctionEntry * auction, SQLTransaction& trans); + void SendAuctionOutbiddedMail(AuctionEntry * auction, uint32 newPrice, Player* newBidder, SQLTransaction& trans); + void SendAuctionCancelledToBidderMail(AuctionEntry* auction, SQLTransaction& trans); + static uint32 GetAuctionDeposit(AuctionHouseEntry const* entry, uint32 time, Item *pItem); static AuctionHouseEntry const* GetAuctionHouseEntry(uint32 factionTemplateId); diff --git a/src/server/game/Battlegrounds/ArenaTeam.cpp b/src/server/game/Battlegrounds/ArenaTeam.cpp index 51c5cecd6f6..d72aa75b952 100644 --- a/src/server/game/Battlegrounds/ArenaTeam.cpp +++ b/src/server/game/Battlegrounds/ArenaTeam.cpp @@ -78,16 +78,16 @@ bool ArenaTeam::Create(uint64 captainGuid, uint32 type, std::string ArenaTeamNam // ArenaTeamName already assigned to ArenaTeam::name, use it to encode string for DB CharacterDatabase.escape_string(ArenaTeamName); - CharacterDatabase.BeginTransaction(); + SQLTransaction trans = CharacterDatabase.BeginTransaction(); // CharacterDatabase.PExecute("DELETE FROM arena_team WHERE arenateamid='%u'", m_TeamId); - MAX(arenateam)+1 not exist - CharacterDatabase.PExecute("DELETE FROM arena_team_member WHERE arenateamid='%u'", m_TeamId); - CharacterDatabase.PExecute("INSERT INTO arena_team (arenateamid,name,captainguid,type,BackgroundColor,EmblemStyle,EmblemColor,BorderStyle,BorderColor) " + trans->PAppend("DELETE FROM arena_team_member WHERE arenateamid='%u'", m_TeamId); + trans->PAppend("INSERT INTO arena_team (arenateamid,name,captainguid,type,BackgroundColor,EmblemStyle,EmblemColor,BorderStyle,BorderColor) " "VALUES('%u','%s','%u','%u','%u','%u','%u','%u','%u')", m_TeamId, ArenaTeamName.c_str(), GUID_LOPART(m_CaptainGuid), m_Type, m_BackgroundColor, m_EmblemStyle, m_EmblemColor, m_BorderStyle, m_BorderColor); - CharacterDatabase.PExecute("INSERT INTO arena_team_stats (arenateamid, rating, games, wins, played, wins2, rank) VALUES " + trans->PAppend("INSERT INTO arena_team_stats (arenateamid, rating, games, wins, played, wins2, rank) VALUES " "('%u', '%u', '%u', '%u', '%u', '%u', '%u')", m_TeamId, m_stats.rating, m_stats.games_week, m_stats.wins_week, m_stats.games_season, m_stats.wins_season, m_stats.rank); - CharacterDatabase.CommitTransaction(); + CharacterDatabase.CommitTransaction(trans); AddMember(m_CaptainGuid); sLog.outArena("New ArenaTeam created [Id: %u] [Type: %u] [Captain GUID: %u]", GetId(), GetType(), GetCaptain()); @@ -320,11 +320,11 @@ void ArenaTeam::Disband(WorldSession *session) if (Player *player = session->GetPlayer()) sLog.outArena("Player: %s [GUID: %u] disbanded arena team type: %u [Id: %u].", player->GetName(), player->GetGUIDLow(), GetType(), GetId()); - CharacterDatabase.BeginTransaction(); - CharacterDatabase.PExecute("DELETE FROM arena_team WHERE arenateamid = '%u'", m_TeamId); - CharacterDatabase.PExecute("DELETE FROM arena_team_member WHERE arenateamid = '%u'", m_TeamId); //< this should be alredy done by calling DelMember(memberGuids[j]); for each member - CharacterDatabase.PExecute("DELETE FROM arena_team_stats WHERE arenateamid = '%u'", m_TeamId); - CharacterDatabase.CommitTransaction(); + SQLTransaction trans = CharacterDatabase.BeginTransaction(); + trans->PAppend("DELETE FROM arena_team WHERE arenateamid = '%u'", m_TeamId); + trans->PAppend("DELETE FROM arena_team_member WHERE arenateamid = '%u'", m_TeamId); //< this should be alredy done by calling DelMember(memberGuids[j]); for each member + trans->PAppend("DELETE FROM arena_team_stats WHERE arenateamid = '%u'", m_TeamId); + CharacterDatabase.CommitTransaction(trans); sObjectMgr.RemoveArenaTeam(m_TeamId); } @@ -734,13 +734,11 @@ void ArenaTeam::SaveToDB() { // save team and member stats to db // called after a match has ended, or when calculating arena_points - CharacterDatabase.BeginTransaction(); - CharacterDatabase.PExecute("UPDATE arena_team_stats SET rating = '%u',games = '%u',played = '%u',rank = '%u',wins = '%u',wins2 = '%u' WHERE arenateamid = '%u'", m_stats.rating, m_stats.games_week, m_stats.games_season, m_stats.rank, m_stats.wins_week, m_stats.wins_season, GetId()); + SQLTransaction trans = CharacterDatabase.BeginTransaction(); + trans->PAppend("UPDATE arena_team_stats SET rating = '%u',games = '%u',played = '%u',rank = '%u',wins = '%u',wins2 = '%u' WHERE arenateamid = '%u'", m_stats.rating, m_stats.games_week, m_stats.games_season, m_stats.rank, m_stats.wins_week, m_stats.wins_season, GetId()); for (MemberList::const_iterator itr = m_members.begin(); itr != m_members.end(); ++itr) - { - CharacterDatabase.PExecute("UPDATE arena_team_member SET played_week = '%u', wons_week = '%u', played_season = '%u', wons_season = '%u', personal_rating = '%u' WHERE arenateamid = '%u' AND guid = '%u'", itr->games_week, itr->wins_week, itr->games_season, itr->wins_season, itr->personal_rating, m_TeamId, GUID_LOPART(itr->guid)); - } - CharacterDatabase.CommitTransaction(); + trans->PAppend("UPDATE arena_team_member SET played_week = '%u', wons_week = '%u', played_season = '%u', wons_season = '%u', personal_rating = '%u' WHERE arenateamid = '%u' AND guid = '%u'", itr->games_week, itr->wins_week, itr->games_season, itr->wins_season, itr->personal_rating, m_TeamId, GUID_LOPART(itr->guid)); + CharacterDatabase.CommitTransaction(trans); } void ArenaTeam::FinishWeek() diff --git a/src/server/game/Chat/Commands/Level1.cpp b/src/server/game/Chat/Commands/Level1.cpp index f483dc2540e..c9ef15c50ad 100644 --- a/src/server/game/Chat/Commands/Level1.cpp +++ b/src/server/game/Chat/Commands/Level1.cpp @@ -2395,8 +2395,12 @@ bool ChatHandler::HandleSendMailCommand(const char* args) // from console show not existed sender MailSender sender(MAIL_NORMAL,m_session ? m_session->GetPlayer()->GetGUIDLow() : 0, MAIL_STATIONERY_GM); + //- TODO: Fix poor design + SQLTransaction trans = CharacterDatabase.BeginTransaction(); MailDraft(subject, text) - .SendMailTo(MailReceiver(target,GUID_LOPART(target_guid)),sender); + .SendMailTo(trans, MailReceiver(target,GUID_LOPART(target_guid)),sender); + + CharacterDatabase.CommitTransaction(trans); std::string nameLink = playerLink(target_name); PSendSysMessage(LANG_MAIL_SENT, nameLink.c_str()); diff --git a/src/server/game/Chat/Commands/Level3.cpp b/src/server/game/Chat/Commands/Level3.cpp index 14cf5e0b858..d712dcdac91 100644 --- a/src/server/game/Chat/Commands/Level3.cpp +++ b/src/server/game/Chat/Commands/Level3.cpp @@ -6818,16 +6818,19 @@ bool ChatHandler::HandleSendItemsCommand(const char *args) // fill mail MailDraft draft(subject, text); + SQLTransaction trans = CharacterDatabase.BeginTransaction(); + for (ItemPairs::const_iterator itr = items.begin(); itr != items.end(); ++itr) { if (Item* item = Item::CreateItem(itr->first,itr->second,m_session ? m_session->GetPlayer() : 0)) { - item->SaveToDB(); // save for prevent lost at next mail load, if send fail then item will deleted + item->SaveToDB(trans); // save for prevent lost at next mail load, if send fail then item will deleted draft.AddItem(item); } } - draft.SendMailTo(MailReceiver(receiver,GUID_LOPART(receiver_guid)), sender); + draft.SendMailTo(trans, MailReceiver(receiver,GUID_LOPART(receiver_guid)), sender); + CharacterDatabase.CommitTransaction(trans); std::string nameLink = playerLink(receiver_name); PSendSysMessage(LANG_MAIL_SENT, nameLink.c_str()); @@ -6873,9 +6876,13 @@ bool ChatHandler::HandleSendMoneyCommand(const char *args) // from console show not existed sender MailSender sender(MAIL_NORMAL,m_session ? m_session->GetPlayer()->GetGUIDLow() : 0, MAIL_STATIONERY_GM); + SQLTransaction trans = CharacterDatabase.BeginTransaction(); + MailDraft(subject, text) .AddMoney(money) - .SendMailTo(MailReceiver(receiver,GUID_LOPART(receiver_guid)),sender); + .SendMailTo(trans, MailReceiver(receiver,GUID_LOPART(receiver_guid)),sender); + + CharacterDatabase.CommitTransaction(trans); std::string nameLink = playerLink(receiver_name); PSendSysMessage(LANG_MAIL_SENT, nameLink.c_str()); diff --git a/src/server/game/Entities/Corpse/Corpse.cpp b/src/server/game/Entities/Corpse/Corpse.cpp index 8bc557964c2..dff6caf5d94 100644 --- a/src/server/game/Entities/Corpse/Corpse.cpp +++ b/src/server/game/Entities/Corpse/Corpse.cpp @@ -105,8 +105,8 @@ bool Corpse::Create(uint32 guidlow, Player *owner) void Corpse::SaveToDB() { // prevent DB data inconsistence problems and duplicates - CharacterDatabase.BeginTransaction(); - DeleteFromDB(); + SQLTransaction trans = CharacterDatabase.BeginTransaction(); + DeleteFromDB(trans); std::ostringstream ss; ss << "INSERT INTO corpse (guid,player,position_x,position_y,position_z,orientation,zone,map,displayId,itemCache,bytes1,bytes2,guild,flags,dynFlags,time,corpse_type,instance,phaseMask) VALUES (" @@ -131,8 +131,8 @@ void Corpse::SaveToDB() << uint32(GetType()) << ", " << int(GetInstanceId()) << ", " << uint16(GetPhaseMask()) << ")"; // prevent out of range error - CharacterDatabase.Execute(ss.str().c_str()); - CharacterDatabase.CommitTransaction(); + trans->Append(ss.str().c_str()); + CharacterDatabase.CommitTransaction(trans); } void Corpse::DeleteBonesFromWorld() @@ -149,14 +149,14 @@ void Corpse::DeleteBonesFromWorld() AddObjectToRemoveList(); } -void Corpse::DeleteFromDB() +void Corpse::DeleteFromDB(SQLTransaction& trans) { if (GetType() == CORPSE_BONES) // only specific bones - CharacterDatabase.PExecute("DELETE FROM corpse WHERE guid = '%d'", GetGUIDLow()); + trans->PAppend("DELETE FROM corpse WHERE guid = '%d'", GetGUIDLow()); else // all corpses (not bones) - CharacterDatabase.PExecute("DELETE FROM corpse WHERE player = '%d' AND corpse_type <> '0'", GUID_LOPART(GetOwnerGUID())); + trans->PAppend("DELETE FROM corpse WHERE player = '%d' AND corpse_type <> '0'", GUID_LOPART(GetOwnerGUID())); } bool Corpse::LoadFromDB(uint32 guid, Field *fields) diff --git a/src/server/game/Entities/Corpse/Corpse.h b/src/server/game/Entities/Corpse/Corpse.h index e3d8c702972..d3bb6fbf6a6 100644 --- a/src/server/game/Entities/Corpse/Corpse.h +++ b/src/server/game/Entities/Corpse/Corpse.h @@ -64,7 +64,7 @@ class Corpse : public WorldObject, public GridObject<Corpse> bool LoadFromDB(uint32 guid, Field *fields); void DeleteBonesFromWorld(); - void DeleteFromDB(); + void DeleteFromDB(SQLTransaction& trans); uint64 const& GetOwnerGUID() const { return GetUInt64Value(CORPSE_FIELD_OWNER); } diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index f64cdb57e5f..0f2bbcab186 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -1052,9 +1052,9 @@ void Creature::SaveToDB(uint32 mapid, uint8 spawnMask, uint32 phaseMask) data.spawnMask = spawnMask; // updated in DB - WorldDatabase.BeginTransaction(); + SQLTransaction trans = WorldDatabase.BeginTransaction(); - WorldDatabase.PExecute("DELETE FROM creature WHERE guid = '%u'", m_DBTableGuid); + trans->PAppend("DELETE FROM creature WHERE guid = '%u'", m_DBTableGuid); std::ostringstream ss; ss << "INSERT INTO creature VALUES (" @@ -1077,9 +1077,9 @@ void Creature::SaveToDB(uint32 mapid, uint8 spawnMask, uint32 phaseMask) << (m_isDeadByDefault ? 1 : 0) << "," //is_dead << GetDefaultMovementType() << ")"; //default movement generator type - WorldDatabase.PExecute(ss.str().c_str()); + trans->Append(ss.str().c_str()); - WorldDatabase.CommitTransaction(); + WorldDatabase.CommitTransaction(trans); } void Creature::SelectLevel(const CreatureInfo *cinfo) @@ -1348,12 +1348,12 @@ void Creature::DeleteFromDB() sObjectMgr.SaveCreatureRespawnTime(m_DBTableGuid,GetInstanceId(),0); sObjectMgr.DeleteCreatureData(m_DBTableGuid); - WorldDatabase.BeginTransaction(); - WorldDatabase.PExecute("DELETE FROM creature WHERE guid = '%u'", m_DBTableGuid); - WorldDatabase.PExecute("DELETE FROM creature_addon WHERE guid = '%u'", m_DBTableGuid); - WorldDatabase.PExecute("DELETE FROM game_event_creature WHERE guid = '%u'", m_DBTableGuid); - WorldDatabase.PExecute("DELETE FROM game_event_model_equip WHERE guid = '%u'", m_DBTableGuid); - WorldDatabase.CommitTransaction(); + SQLTransaction trans = WorldDatabase.BeginTransaction(); + trans->PAppend("DELETE FROM creature WHERE guid = '%u'", m_DBTableGuid); + trans->PAppend("DELETE FROM creature_addon WHERE guid = '%u'", m_DBTableGuid); + trans->PAppend("DELETE FROM game_event_creature WHERE guid = '%u'", m_DBTableGuid); + trans->PAppend("DELETE FROM game_event_model_equip WHERE guid = '%u'", m_DBTableGuid); + WorldDatabase.CommitTransaction(trans); } bool Creature::canSeeOrDetect(Unit const* u, bool detect, bool /*inVisibleList*/, bool /*is3dDistance*/) const diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp index 89f17450a83..f1c823001bc 100644 --- a/src/server/game/Entities/GameObject/GameObject.cpp +++ b/src/server/game/Entities/GameObject/GameObject.cpp @@ -644,10 +644,10 @@ void GameObject::SaveToDB(uint32 mapid, uint8 spawnMask, uint32 phaseMask) << uint32(GetGoAnimProgress()) << ", " << uint32(GetGoState()) << ")"; - WorldDatabase.BeginTransaction(); - WorldDatabase.PExecute("DELETE FROM gameobject WHERE guid = '%u'", m_DBTableGuid); - WorldDatabase.PExecute(ss.str().c_str()); - WorldDatabase.CommitTransaction(); + SQLTransaction trans = WorldDatabase.BeginTransaction(); + trans->PAppend("DELETE FROM gameobject WHERE guid = '%u'", m_DBTableGuid); + trans->Append(ss.str().c_str()); + WorldDatabase.CommitTransaction(trans); } bool GameObject::LoadFromDB(uint32 guid, Map *map) diff --git a/src/server/game/Entities/Item/Container/Bag.cpp b/src/server/game/Entities/Item/Container/Bag.cpp index 8a1e978b73f..c5f747ff322 100644 --- a/src/server/game/Entities/Item/Container/Bag.cpp +++ b/src/server/game/Entities/Item/Container/Bag.cpp @@ -102,9 +102,9 @@ bool Bag::Create(uint32 guidlow, uint32 itemid, Player const* owner) return true; } -void Bag::SaveToDB() +void Bag::SaveToDB(SQLTransaction& trans) { - Item::SaveToDB(); + Item::SaveToDB(trans); } bool Bag::LoadFromDB(uint32 guid, uint64 owner_guid, QueryResult_AutoPtr result, uint32 entry) @@ -125,13 +125,13 @@ bool Bag::LoadFromDB(uint32 guid, uint64 owner_guid, QueryResult_AutoPtr result, return true; } -void Bag::DeleteFromDB() +void Bag::DeleteFromDB(SQLTransaction& trans) { for (uint8 i = 0; i < MAX_BAG_SIZE; ++i) if (m_bagslot[i]) - m_bagslot[i]->DeleteFromDB(); + m_bagslot[i]->DeleteFromDB(trans); - Item::DeleteFromDB(); + Item::DeleteFromDB(trans); } uint32 Bag::GetFreeSlots() const diff --git a/src/server/game/Entities/Item/Container/Bag.h b/src/server/game/Entities/Item/Container/Bag.h index 6d4f65cf8cc..c704272309b 100644 --- a/src/server/game/Entities/Item/Container/Bag.h +++ b/src/server/game/Entities/Item/Container/Bag.h @@ -54,11 +54,11 @@ class Bag : public Item // DB operations // overwrite virtual Item::SaveToDB - void SaveToDB(); + void SaveToDB(SQLTransaction& trans); // overwrite virtual Item::LoadFromDB bool LoadFromDB(uint32 guid, uint64 owner_guid, QueryResult_AutoPtr result, uint32 entry); // overwrite virtual Item::DeleteFromDB - void DeleteFromDB(); + void DeleteFromDB(SQLTransaction& trans); void BuildCreateUpdateBlockForPlayer(UpdateData *data, Player *target) const; diff --git a/src/server/game/Entities/Item/Item.cpp b/src/server/game/Entities/Item/Item.cpp index ef7ac10634a..4e615052cba 100644 --- a/src/server/game/Entities/Item/Item.cpp +++ b/src/server/game/Entities/Item/Item.cpp @@ -301,7 +301,7 @@ void Item::UpdateDuration(Player* owner, uint32 diff) SetState(ITEM_CHANGED, owner); // save new time in database } -void Item::SaveToDB() +void Item::SaveToDB(SQLTransaction& trans) { uint32 guid = GetGUIDLow(); switch (uState) @@ -334,7 +334,7 @@ void Item::SaveToDB() ss << GetUInt32Value(ITEM_FIELD_CREATE_PLAYED_TIME) << ",'"; ss << text << "')"; - CharacterDatabase.Execute(ss.str().c_str()); + trans->Append(ss.str().c_str()); }break; case ITEM_CHANGED: { @@ -364,16 +364,16 @@ void Item::SaveToDB() ss << ", playedTime = " << GetUInt32Value(ITEM_FIELD_CREATE_PLAYED_TIME); ss << ", text = '" << text << "' WHERE guid = " << guid; - CharacterDatabase.Execute(ss.str().c_str()); + trans->Append(ss.str().c_str()); if (HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_WRAPPED)) - CharacterDatabase.PExecute("UPDATE character_gifts SET guid = '%u' WHERE item_guid = '%u'", GUID_LOPART(GetOwnerGUID()),GetGUIDLow()); + trans->PAppend("UPDATE character_gifts SET guid = '%u' WHERE item_guid = '%u'", GUID_LOPART(GetOwnerGUID()),GetGUIDLow()); }break; case ITEM_REMOVED: { - CharacterDatabase.PExecute("DELETE FROM item_instance WHERE guid = '%u'", guid); + trans->PAppend("DELETE FROM item_instance WHERE guid = '%u'", guid); if (HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_WRAPPED)) - CharacterDatabase.PExecute("DELETE FROM character_gifts WHERE item_guid = '%u'", GetGUIDLow()); + trans->PAppend("DELETE FROM character_gifts WHERE item_guid = '%u'", GetGUIDLow()); delete this; return; } @@ -471,14 +471,14 @@ bool Item::LoadFromDB(uint32 guid, uint64 owner_guid, QueryResult_AutoPtr result return true; } -void Item::DeleteFromDB() +void Item::DeleteFromDB(SQLTransaction& trans) { - CharacterDatabase.PExecute("DELETE FROM item_instance WHERE guid = '%u'",GetGUIDLow()); + trans->PAppend("DELETE FROM item_instance WHERE guid = '%u'",GetGUIDLow()); } -void Item::DeleteFromInventoryDB() +void Item::DeleteFromInventoryDB(SQLTransaction& trans) { - CharacterDatabase.PExecute("DELETE FROM character_inventory WHERE item = '%u'",GetGUIDLow()); + trans->PAppend("DELETE FROM character_inventory WHERE item = '%u'",GetGUIDLow()); } ItemPrototype const *Item::GetProto() const @@ -1103,11 +1103,11 @@ void Item::BuildUpdate(UpdateDataMapType& data_map) void Item::SaveRefundDataToDB() { - CharacterDatabase.BeginTransaction(); - CharacterDatabase.PExecute("DELETE FROM item_refund_instance WHERE item_guid = '%u'", GetGUIDLow()); - CharacterDatabase.PExecute("INSERT INTO item_refund_instance (`item_guid`,`player_guid`,`paidMoney`,`paidExtendedCost`)" + SQLTransaction trans = CharacterDatabase.BeginTransaction(); + trans->PAppend("DELETE FROM item_refund_instance WHERE item_guid = '%u'", GetGUIDLow()); + trans->PAppend("INSERT INTO item_refund_instance (`item_guid`,`player_guid`,`paidMoney`,`paidExtendedCost`)" " VALUES('%u','%u','%u','%u')", GetGUIDLow(), GetRefundRecipient(), GetPaidMoney(), GetPaidExtendedCost()); - CharacterDatabase.CommitTransaction(); + CharacterDatabase.CommitTransaction(trans); } void Item::DeleteRefundDataFromDB() diff --git a/src/server/game/Entities/Item/Item.h b/src/server/game/Entities/Item/Item.h index bab9bc9060a..25b4b69a607 100644 --- a/src/server/game/Entities/Item/Item.h +++ b/src/server/game/Entities/Item/Item.h @@ -244,10 +244,10 @@ class Item : public Object bool IsBoundAccountWide() const { return (GetProto()->Flags & ITEM_PROTO_FLAG_BIND_TO_ACCOUNT) != 0; } bool IsBindedNotWith(Player const* player) const; bool IsBoundByEnchant() const; - virtual void SaveToDB(); + virtual void SaveToDB(SQLTransaction& trans); virtual bool LoadFromDB(uint32 guid, uint64 owner_guid, QueryResult_AutoPtr result, uint32 entry); - virtual void DeleteFromDB(); - void DeleteFromInventoryDB(); + virtual void DeleteFromDB(SQLTransaction& trans); + void DeleteFromInventoryDB(SQLTransaction& trans); void SaveRefundDataToDB(); void DeleteRefundDataFromDB(); diff --git a/src/server/game/Entities/Pet/Pet.cpp b/src/server/game/Entities/Pet/Pet.cpp index e6ee2dcae74..f5780f1c696 100644 --- a/src/server/game/Entities/Pet/Pet.cpp +++ b/src/server/game/Entities/Pet/Pet.cpp @@ -262,12 +262,12 @@ bool Pet::LoadPetFromDB(Player* owner, uint32 petentry, uint32 petnumber, bool c // PET_SAVE_NOT_IN_SLOT(100) = not stable slot (summoning)) if (fields[7].GetUInt32() != 0) { - CharacterDatabase.BeginTransaction(); - CharacterDatabase.PExecute("UPDATE character_pet SET slot = '%u' WHERE owner = '%u' AND slot = '%u' AND id <> '%u'", + SQLTransaction trans = CharacterDatabase.BeginTransaction(); + trans->PAppend("UPDATE character_pet SET slot = '%u' WHERE owner = '%u' AND slot = '%u' AND id <> '%u'", PET_SAVE_NOT_IN_SLOT, ownerid, PET_SAVE_AS_CURRENT, m_charmInfo->GetPetNumber()); - CharacterDatabase.PExecute("UPDATE character_pet SET slot = '%u' WHERE owner = '%u' AND id = '%u'", + trans->PAppend("UPDATE character_pet SET slot = '%u' WHERE owner = '%u' AND id = '%u'", PET_SAVE_AS_CURRENT, ownerid, m_charmInfo->GetPetNumber()); - CharacterDatabase.CommitTransaction(); + CharacterDatabase.CommitTransaction(trans); } // Send fake summon spell cast - this is needed for correct cooldown application for spells @@ -377,19 +377,17 @@ void Pet::SavePetToDB(PetSaveMode mode) uint32 curhealth = GetHealth(); uint32 curmana = GetPower(POWER_MANA); - CharacterDatabase.BeginTransaction(); + SQLTransaction trans = CharacterDatabase.BeginTransaction(); // save auras before possibly removing them - _SaveAuras(); + _SaveAuras(trans); // stable and not in slot saves if (mode > PET_SAVE_AS_CURRENT) - { RemoveAllAuras(); - } - _SaveSpells(); - _SaveSpellCooldowns(); - CharacterDatabase.CommitTransaction(); + _SaveSpells(trans); + _SaveSpellCooldowns(trans); + CharacterDatabase.CommitTransaction(trans); // current/stable/not_in_slot if (mode >= PET_SAVE_AS_CURRENT) @@ -397,18 +395,18 @@ void Pet::SavePetToDB(PetSaveMode mode) uint32 owner = GUID_LOPART(GetOwnerGUID()); std::string name = m_name; CharacterDatabase.escape_string(name); - CharacterDatabase.BeginTransaction(); + SQLTransaction trans = CharacterDatabase.BeginTransaction(); // remove current data - CharacterDatabase.PExecute("DELETE FROM character_pet WHERE owner = '%u' AND id = '%u'", owner,m_charmInfo->GetPetNumber()); + trans->PAppend("DELETE FROM character_pet WHERE owner = '%u' AND id = '%u'", owner,m_charmInfo->GetPetNumber()); // prevent duplicate using slot (except PET_SAVE_NOT_IN_SLOT) if (mode <= PET_SAVE_LAST_STABLE_SLOT) - CharacterDatabase.PExecute("UPDATE character_pet SET slot = '%u' WHERE owner = '%u' AND slot = '%u'", + trans->PAppend("UPDATE character_pet SET slot = '%u' WHERE owner = '%u' AND slot = '%u'", PET_SAVE_NOT_IN_SLOT, owner, uint32(mode)); // prevent existence another hunter pet in PET_SAVE_AS_CURRENT and PET_SAVE_NOT_IN_SLOT if (getPetType() == HUNTER_PET && (mode == PET_SAVE_AS_CURRENT||mode > PET_SAVE_LAST_STABLE_SLOT)) - CharacterDatabase.PExecute("DELETE FROM character_pet WHERE owner = '%u' AND (slot = '%u' OR slot > '%u')", + trans->PAppend("DELETE FROM character_pet WHERE owner = '%u' AND (slot = '%u' OR slot > '%u')", owner,PET_SAVE_AS_CURRENT,PET_SAVE_LAST_STABLE_SLOT); // save pet std::ostringstream ss; @@ -441,8 +439,8 @@ void Pet::SavePetToDB(PetSaveMode mode) << GetUInt32Value(UNIT_CREATED_BY_SPELL) << ", " << uint32(getPetType()) << ")"; - CharacterDatabase.Execute(ss.str().c_str()); - CharacterDatabase.CommitTransaction(); + trans->Append(ss.str().c_str()); + CharacterDatabase.CommitTransaction(trans); } // delete else @@ -454,13 +452,13 @@ void Pet::SavePetToDB(PetSaveMode mode) void Pet::DeleteFromDB(uint32 guidlow) { - CharacterDatabase.BeginTransaction(); - CharacterDatabase.PExecute("DELETE FROM character_pet WHERE id = '%u'", guidlow); - CharacterDatabase.PExecute("DELETE FROM character_pet_declinedname WHERE id = '%u'", guidlow); - CharacterDatabase.PExecute("DELETE FROM pet_aura WHERE guid = '%u'", guidlow); - CharacterDatabase.PExecute("DELETE FROM pet_spell WHERE guid = '%u'", guidlow); - CharacterDatabase.PExecute("DELETE FROM pet_spell_cooldown WHERE guid = '%u'", guidlow); - CharacterDatabase.CommitTransaction(); + SQLTransaction trans = CharacterDatabase.BeginTransaction(); + trans->PAppend("DELETE FROM character_pet WHERE id = '%u'", guidlow); + trans->PAppend("DELETE FROM character_pet_declinedname WHERE id = '%u'", guidlow); + trans->PAppend("DELETE FROM pet_aura WHERE guid = '%u'", guidlow); + trans->PAppend("DELETE FROM pet_spell WHERE guid = '%u'", guidlow); + trans->PAppend("DELETE FROM pet_spell_cooldown WHERE guid = '%u'", guidlow); + CharacterDatabase.CommitTransaction(trans); } void Pet::setDeathState(DeathState s) // overwrite virtual Creature::setDeathState and Unit::setDeathState @@ -1143,9 +1141,9 @@ void Pet::_LoadSpellCooldowns() } } -void Pet::_SaveSpellCooldowns() +void Pet::_SaveSpellCooldowns(SQLTransaction& trans) { - CharacterDatabase.PExecute("DELETE FROM pet_spell_cooldown WHERE guid = '%u'", m_charmInfo->GetPetNumber()); + trans->PAppend("DELETE FROM pet_spell_cooldown WHERE guid = '%u'", m_charmInfo->GetPetNumber()); time_t curTime = time(NULL); @@ -1156,7 +1154,7 @@ void Pet::_SaveSpellCooldowns() m_CreatureSpellCooldowns.erase(itr++); else { - CharacterDatabase.PExecute("INSERT INTO pet_spell_cooldown (guid,spell,time) VALUES ('%u', '%u', '" UI64FMTD "')", m_charmInfo->GetPetNumber(), itr->first, uint64(itr->second)); + trans->PAppend("INSERT INTO pet_spell_cooldown (guid,spell,time) VALUES ('%u', '%u', '" UI64FMTD "')", m_charmInfo->GetPetNumber(), itr->first, uint64(itr->second)); ++itr; } } @@ -1178,7 +1176,7 @@ void Pet::_LoadSpells() } } -void Pet::_SaveSpells() +void Pet::_SaveSpells(SQLTransaction& trans) { for (PetSpellMap::iterator itr = m_spells.begin(), next = m_spells.begin(); itr != m_spells.end(); itr = next) { @@ -1191,15 +1189,15 @@ void Pet::_SaveSpells() switch (itr->second.state) { case PETSPELL_REMOVED: - CharacterDatabase.PExecute("DELETE FROM pet_spell WHERE guid = '%u' and spell = '%u'", m_charmInfo->GetPetNumber(), itr->first); + trans->PAppend("DELETE FROM pet_spell WHERE guid = '%u' and spell = '%u'", m_charmInfo->GetPetNumber(), itr->first); m_spells.erase(itr); continue; case PETSPELL_CHANGED: - CharacterDatabase.PExecute("DELETE FROM pet_spell WHERE guid = '%u' and spell = '%u'", m_charmInfo->GetPetNumber(), itr->first); - CharacterDatabase.PExecute("INSERT INTO pet_spell (guid,spell,active) VALUES ('%u', '%u', '%u')", m_charmInfo->GetPetNumber(), itr->first, itr->second.active); + trans->PAppend("DELETE FROM pet_spell WHERE guid = '%u' and spell = '%u'", m_charmInfo->GetPetNumber(), itr->first); + trans->PAppend("INSERT INTO pet_spell (guid,spell,active) VALUES ('%u', '%u', '%u')", m_charmInfo->GetPetNumber(), itr->first, itr->second.active); break; case PETSPELL_NEW: - CharacterDatabase.PExecute("INSERT INTO pet_spell (guid,spell,active) VALUES ('%u', '%u', '%u')", m_charmInfo->GetPetNumber(), itr->first, itr->second.active); + trans->PAppend("INSERT INTO pet_spell (guid,spell,active) VALUES ('%u', '%u', '%u')", m_charmInfo->GetPetNumber(), itr->first, itr->second.active); break; case PETSPELL_UNCHANGED: continue; @@ -1278,9 +1276,9 @@ void Pet::_LoadAuras(uint32 timediff) } } -void Pet::_SaveAuras() +void Pet::_SaveAuras(SQLTransaction& trans) { - CharacterDatabase.PExecute("DELETE FROM pet_aura WHERE guid = '%u'", m_charmInfo->GetPetNumber()); + trans->PAppend("DELETE FROM pet_aura WHERE guid = '%u'", m_charmInfo->GetPetNumber()); for (AuraMap::const_iterator itr = m_ownedAuras.begin(); itr != m_ownedAuras.end() ; ++itr) { @@ -1311,7 +1309,7 @@ void Pet::_SaveAuras() } } - CharacterDatabase.PExecute("INSERT INTO pet_aura (guid,caster_guid,spell,effect_mask,recalculate_mask,stackcount,amount0,amount1,amount2,base_amount0,base_amount1,base_amount2,maxduration,remaintime,remaincharges) " + trans->PAppend("INSERT INTO pet_aura (guid,caster_guid,spell,effect_mask,recalculate_mask,stackcount,amount0,amount1,amount2,base_amount0,base_amount1,base_amount2,maxduration,remaintime,remaincharges) " "VALUES ('%u', '" UI64FMTD "', '%u', '%u', '%u', '%u', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%u')", m_charmInfo->GetPetNumber(), itr->second->GetCasterGUID(), itr->second->GetId(), effMask, recalculateMask, itr->second->GetStackAmount(), damage[0], damage[1], damage[2], baseDamage[0], baseDamage[1], baseDamage[2], diff --git a/src/server/game/Entities/Pet/Pet.h b/src/server/game/Entities/Pet/Pet.h index 36e4b7ce727..48f36ca8c07 100644 --- a/src/server/game/Entities/Pet/Pet.h +++ b/src/server/game/Entities/Pet/Pet.h @@ -191,11 +191,11 @@ class Pet : public Guardian bool IsPetAura(Aura const* aura); void _LoadSpellCooldowns(); - void _SaveSpellCooldowns(); + void _SaveSpellCooldowns(SQLTransaction& trans); void _LoadAuras(uint32 timediff); - void _SaveAuras(); + void _SaveAuras(SQLTransaction& trans); void _LoadSpells(); - void _SaveSpells(); + void _SaveSpells(SQLTransaction& trans); bool addSpell(uint32 spell_id,ActiveStates active = ACT_DECIDE, PetSpellState state = PETSPELL_NEW, PetSpellType type = PETSPELL_NORMAL); bool learnSpell(uint32 spell_id); diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index f016bb88117..4a1bab14cd1 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -2736,7 +2736,12 @@ void Player::GiveLevel(uint8 level) pet->SynchronizeLevelWithOwner(); if (MailLevelReward const* mailReward = sObjectMgr.GetMailLevelReward(level,getRaceMask())) - MailDraft(mailReward->mailTemplateId).SendMailTo(this,MailSender(MAIL_CREATURE,mailReward->senderEntry)); + { + //- TODO: Poor design of mail system + SQLTransaction trans = CharacterDatabase.BeginTransaction(); + MailDraft(mailReward->mailTemplateId).SendMailTo(trans, this,MailSender(MAIL_CREATURE,mailReward->senderEntry)); + CharacterDatabase.CommitTransaction(trans); + } GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL); } @@ -3925,9 +3930,9 @@ void Player::_LoadSpellCooldowns(QueryResult_AutoPtr result) } } -void Player::_SaveSpellCooldowns() +void Player::_SaveSpellCooldowns(SQLTransaction& trans) { - CharacterDatabase.PExecute("DELETE FROM character_spell_cooldown WHERE guid = '%u'", GetGUIDLow()); + trans->PAppend("DELETE FROM character_spell_cooldown WHERE guid = '%u'", GetGUIDLow()); time_t curTime = time(NULL); time_t infTime = curTime + infinityCooldownDelayCheck; @@ -3959,7 +3964,7 @@ void Player::_SaveSpellCooldowns() } // if something changed execute if (!first_round) - CharacterDatabase.Execute(ss.str().c_str()); + trans->Append(ss.str().c_str()); } uint32 Player::resetTalentsCost() const @@ -4059,7 +4064,9 @@ bool Player::resetTalents(bool no_cost) } } - _SaveSpells(); + SQLTransaction trans = CharacterDatabase.BeginTransaction(); + _SaveSpells(trans); + CharacterDatabase.CommitTransaction(trans); SetFreeTalentPoints(talentPointsForLevel); @@ -4416,6 +4423,7 @@ void Player::DeleteFromDB(uint64 playerguid, uint32 accountId, bool updateRealmC // Completely remove from the database case CHAR_DELETE_REMOVE: { + SQLTransaction trans = CharacterDatabase.BeginTransaction(); // Return back all mails with COD and Item 0 1 2 3 4 5 6 7 QueryResult_AutoPtr resultMail = CharacterDatabase.PQuery("SELECT id,messageType,mailTemplateId,sender,subject,body,money,has_items FROM mail WHERE receiver='%u' AND has_items<>0 AND cod<>0", guid); if (resultMail) @@ -4435,13 +4443,13 @@ void Player::DeleteFromDB(uint64 playerguid, uint32 accountId, bool updateRealmC // We can return mail now // So firstly delete the old one - CharacterDatabase.PExecute("DELETE FROM mail WHERE id = '%u'", mail_id); + trans->PAppend("DELETE FROM mail WHERE id = '%u'", mail_id); // Mail is not from player if (mailType != MAIL_NORMAL) { if (has_items) - CharacterDatabase.PExecute("DELETE FROM mail_items WHERE mail_id = '%u'", mail_id); + trans->PAppend("DELETE FROM mail_items WHERE mail_id = '%u'", mail_id); continue; } @@ -4465,7 +4473,7 @@ void Player::DeleteFromDB(uint64 playerguid, uint32 accountId, bool updateRealmC ItemPrototype const* itemProto = sObjectMgr.GetItemPrototype(item_template); if (!itemProto) { - CharacterDatabase.PExecute("DELETE FROM item_instance WHERE guid = '%u'", item_guidlow); + trans->PAppend("DELETE FROM item_instance WHERE guid = '%u'", item_guidlow); continue; } @@ -4473,7 +4481,7 @@ void Player::DeleteFromDB(uint64 playerguid, uint32 accountId, bool updateRealmC if (!pItem->LoadFromDB(item_guidlow, MAKE_NEW_GUID(guid, 0, HIGHGUID_PLAYER), resultItems, item_template)) { pItem->FSetState(ITEM_REMOVED); - pItem->SaveToDB(); // it also deletes item object! + pItem->SaveToDB(trans); // it also deletes item object! continue; } @@ -4483,7 +4491,7 @@ void Player::DeleteFromDB(uint64 playerguid, uint32 accountId, bool updateRealmC } } - CharacterDatabase.PExecute("DELETE FROM mail_items WHERE mail_id = '%u'", mail_id); + trans->PAppend("DELETE FROM mail_items WHERE mail_id = '%u'", mail_id); uint32 pl_account = sObjectMgr.GetPlayerAccountIdByGUID(MAKE_NEW_GUID(guid, 0, HIGHGUID_PLAYER)); @@ -4497,7 +4505,6 @@ void Player::DeleteFromDB(uint64 playerguid, uint32 accountId, bool updateRealmC QueryResult_AutoPtr resultPets = CharacterDatabase.PQuery("SELECT id FROM character_pet WHERE owner = '%u'",guid); // NOW we can finally clear other DB data related to character - CharacterDatabase.BeginTransaction(); if (resultPets) { do @@ -4508,41 +4515,41 @@ void Player::DeleteFromDB(uint64 playerguid, uint32 accountId, bool updateRealmC } while (resultPets->NextRow()); } - CharacterDatabase.PExecute("DELETE FROM characters WHERE guid = '%u'",guid); - CharacterDatabase.PExecute("DELETE FROM character_account_data WHERE guid = '%u'",guid); - CharacterDatabase.PExecute("DELETE FROM character_declinedname WHERE guid = '%u'",guid); - CharacterDatabase.PExecute("DELETE FROM character_action WHERE guid = '%u'",guid); - CharacterDatabase.PExecute("DELETE FROM character_aura WHERE guid = '%u'",guid); - CharacterDatabase.PExecute("DELETE FROM character_gifts WHERE guid = '%u'",guid); - CharacterDatabase.PExecute("DELETE FROM character_homebind WHERE guid = '%u'",guid); - CharacterDatabase.PExecute("DELETE FROM character_instance WHERE guid = '%u'",guid); - CharacterDatabase.PExecute("DELETE FROM character_inventory WHERE guid = '%u'",guid); - CharacterDatabase.PExecute("DELETE FROM character_queststatus WHERE guid = '%u'",guid); - CharacterDatabase.PExecute("DELETE FROM character_reputation WHERE guid = '%u'",guid); - CharacterDatabase.PExecute("DELETE FROM character_spell WHERE guid = '%u'",guid); - CharacterDatabase.PExecute("DELETE FROM character_spell_cooldown WHERE guid = '%u'",guid); - CharacterDatabase.PExecute("DELETE FROM gm_tickets WHERE playerGuid = '%u'", guid); - CharacterDatabase.PExecute("DELETE FROM item_instance WHERE owner_guid = '%u'",guid); - CharacterDatabase.PExecute("DELETE FROM character_social WHERE guid = '%u' OR friend='%u'",guid,guid); - CharacterDatabase.PExecute("DELETE FROM mail WHERE receiver = '%u'",guid); - CharacterDatabase.PExecute("DELETE FROM mail_items WHERE receiver = '%u'",guid); - CharacterDatabase.PExecute("DELETE FROM character_pet WHERE owner = '%u'",guid); - CharacterDatabase.PExecute("DELETE FROM character_pet_declinedname WHERE owner = '%u'",guid); - CharacterDatabase.PExecute("DELETE FROM character_achievement WHERE guid = '%u' " // NOTE: These achievements have flags & 256 in DBC. + trans->PAppend("DELETE FROM characters WHERE guid = '%u'",guid); + trans->PAppend("DELETE FROM character_account_data WHERE guid = '%u'",guid); + trans->PAppend("DELETE FROM character_declinedname WHERE guid = '%u'",guid); + trans->PAppend("DELETE FROM character_action WHERE guid = '%u'",guid); + trans->PAppend("DELETE FROM character_aura WHERE guid = '%u'",guid); + trans->PAppend("DELETE FROM character_gifts WHERE guid = '%u'",guid); + trans->PAppend("DELETE FROM character_homebind WHERE guid = '%u'",guid); + trans->PAppend("DELETE FROM character_instance WHERE guid = '%u'",guid); + trans->PAppend("DELETE FROM character_inventory WHERE guid = '%u'",guid); + trans->PAppend("DELETE FROM character_queststatus WHERE guid = '%u'",guid); + trans->PAppend("DELETE FROM character_reputation WHERE guid = '%u'",guid); + trans->PAppend("DELETE FROM character_spell WHERE guid = '%u'",guid); + trans->PAppend("DELETE FROM character_spell_cooldown WHERE guid = '%u'",guid); + trans->PAppend("DELETE FROM gm_tickets WHERE playerGuid = '%u'", guid); + trans->PAppend("DELETE FROM item_instance WHERE owner_guid = '%u'",guid); + trans->PAppend("DELETE FROM character_social WHERE guid = '%u' OR friend='%u'",guid,guid); + trans->PAppend("DELETE FROM mail WHERE receiver = '%u'",guid); + trans->PAppend("DELETE FROM mail_items WHERE receiver = '%u'",guid); + trans->PAppend("DELETE FROM character_pet WHERE owner = '%u'",guid); + trans->PAppend("DELETE FROM character_pet_declinedname WHERE owner = '%u'",guid); + trans->PAppend("DELETE FROM character_achievement WHERE guid = '%u' " // NOTE: These achievements have flags & 256 in DBC. "AND achievement NOT BETWEEN '456' AND '467' " // Realm First Level 80 "AND achievement NOT BETWEEN '1400' AND '1427' " // Realm First Raid Achievements "AND achievement NOT IN(1463, 3117, 3259) ", guid); // Realm First Northen Vanguard + Raid Achievements - CharacterDatabase.PExecute("DELETE FROM character_achievement_progress WHERE guid = '%u'",guid); - CharacterDatabase.PExecute("DELETE FROM character_equipmentsets WHERE guid = '%u'",guid); - CharacterDatabase.PExecute("DELETE FROM guild_eventlog WHERE PlayerGuid1 = '%u' OR PlayerGuid2 = '%u'",guid, guid); - CharacterDatabase.PExecute("DELETE FROM guild_bank_eventlog WHERE PlayerGuid = '%u'",guid); - CharacterDatabase.PExecute("DELETE FROM character_battleground_data WHERE guid = '%u'",guid); - CharacterDatabase.PExecute("DELETE FROM character_glyphs WHERE guid = '%u'",guid); - CharacterDatabase.PExecute("DELETE FROM character_queststatus_daily WHERE guid = '%u'",guid); - CharacterDatabase.PExecute("DELETE FROM character_talent WHERE guid = '%u'",guid); - CharacterDatabase.PExecute("DELETE FROM character_skills WHERE guid = '%u'",guid); - - CharacterDatabase.CommitTransaction(); + trans->PAppend("DELETE FROM character_achievement_progress WHERE guid = '%u'",guid); + trans->PAppend("DELETE FROM character_equipmentsets WHERE guid = '%u'",guid); + trans->PAppend("DELETE FROM guild_eventlog WHERE PlayerGuid1 = '%u' OR PlayerGuid2 = '%u'",guid, guid); + trans->PAppend("DELETE FROM guild_bank_eventlog WHERE PlayerGuid = '%u'",guid); + trans->PAppend("DELETE FROM character_battleground_data WHERE guid = '%u'",guid); + trans->PAppend("DELETE FROM character_glyphs WHERE guid = '%u'",guid); + trans->PAppend("DELETE FROM character_queststatus_daily WHERE guid = '%u'",guid); + trans->PAppend("DELETE FROM character_talent WHERE guid = '%u'",guid); + trans->PAppend("DELETE FROM character_skills WHERE guid = '%u'",guid); + + CharacterDatabase.CommitTransaction(trans); break; } // The character gets unlinked from the account, the name gets freed up and appears as deleted ingame @@ -5071,7 +5078,11 @@ uint32 Player::DurabilityRepair(uint16 pos, bool cost, float discountMod, bool g return TotalCost; } - pGuild->MemberMoneyWithdraw(costs, GetGUIDLow()); + //- TODO: Fix bad function call design + SQLTransaction trans = CharacterDatabase.BeginTransaction(); + pGuild->MemberMoneyWithdraw(costs, GetGUIDLow(), trans); + CharacterDatabase.CommitTransaction(trans); + TotalCost = costs; } else if (GetMoney() < costs) @@ -14429,7 +14440,12 @@ void Player::RewardQuest(Quest const *pQuest, uint32 reward, Object* questGiver, // Send reward mail if (uint32 mail_template_id = pQuest->GetRewMailTemplateId()) - MailDraft(mail_template_id).SendMailTo(this, questGiver, MAIL_CHECK_MASK_HAS_BODY, pQuest->GetRewMailDelaySecs()); + { + //- TODO: Poor design of mail system + SQLTransaction trans = CharacterDatabase.BeginTransaction(); + MailDraft(mail_template_id).SendMailTo(trans, this, questGiver, MAIL_CHECK_MASK_HAS_BODY, pQuest->GetRewMailDelaySecs()); + CharacterDatabase.CommitTransaction(trans); + } if (pQuest->IsDaily()) { @@ -16668,6 +16684,7 @@ void Player::_LoadInventory(QueryResult_AutoPtr result, uint32 timediff) if (result) { std::list<Item*> problematicItems; + SQLTransaction trans = CharacterDatabase.BeginTransaction(); // prevent items from being added to the queue when stored m_itemUpdateQueueBlocked = true; @@ -16683,8 +16700,8 @@ void Player::_LoadInventory(QueryResult_AutoPtr result, uint32 timediff) if (!proto) { - CharacterDatabase.PExecute("DELETE FROM character_inventory WHERE item = '%u'", item_guid); - CharacterDatabase.PExecute("DELETE FROM item_instance WHERE guid = '%u'", item_guid); + trans->PAppend("DELETE FROM character_inventory WHERE item = '%u'", item_guid); + trans->PAppend("DELETE FROM item_instance WHERE guid = '%u'", item_guid); sLog.outError("Player::_LoadInventory: Player %s has an unknown item (id: #%u) in inventory, deleted.", GetName(),item_id); continue; } @@ -16696,7 +16713,7 @@ void Player::_LoadInventory(QueryResult_AutoPtr result, uint32 timediff) sLog.outError("Player::_LoadInventory: Player %s has broken item (id: #%u) in inventory, deleted.", GetName(),item_id); CharacterDatabase.PExecute("DELETE FROM character_inventory WHERE item = '%u'", item_guid); item->FSetState(ITEM_REMOVED); - item->SaveToDB(); // it also deletes item object ! + item->SaveToDB(trans); // it also deletes item object ! continue; } @@ -16705,7 +16722,7 @@ void Player::_LoadInventory(QueryResult_AutoPtr result, uint32 timediff) { CharacterDatabase.PExecute("DELETE FROM character_inventory WHERE item = '%u'", item_guid); item->FSetState(ITEM_REMOVED); - item->SaveToDB(); // it also deletes item object ! + item->SaveToDB(trans); // it also deletes item object ! continue; } @@ -16714,7 +16731,7 @@ void Player::_LoadInventory(QueryResult_AutoPtr result, uint32 timediff) { CharacterDatabase.PExecute("DELETE FROM character_inventory WHERE item = '%u'", item_guid); item->FSetState(ITEM_REMOVED); - item->SaveToDB(); // it also deletes item object ! + item->SaveToDB(trans); // it also deletes item object ! continue; } @@ -16723,7 +16740,7 @@ void Player::_LoadInventory(QueryResult_AutoPtr result, uint32 timediff) if (item->GetPlayedTime() > (2*HOUR)) { sLog.outDebug("Item::LoadFromDB, Item GUID: %u: refund time expired, deleting refund data and removing refundable flag.", item->GetGUIDLow()); - CharacterDatabase.PExecute("DELETE FROM item_refund_instance WHERE item_guid = '%u'", item->GetGUIDLow()); + trans->PAppend("DELETE FROM item_refund_instance WHERE item_guid = '%u'", item->GetGUIDLow()); item->RemoveFlag(ITEM_FIELD_FLAGS, ITEM_FLAG_REFUNDABLE); } else @@ -16839,8 +16856,9 @@ void Player::_LoadInventory(QueryResult_AutoPtr result, uint32 timediff) draft.AddItem(item); } - draft.SendMailTo(this, MailSender(this, MAIL_STATIONERY_GM), MAIL_CHECK_MASK_COPIED); + draft.SendMailTo(trans, this, MailSender(this, MAIL_STATIONERY_GM), MAIL_CHECK_MASK_COPIED); } + CharacterDatabase.CommitTransaction(trans); } //if (isAlive()) _ApplyAllItemMods(); @@ -16854,6 +16872,7 @@ void Player::_LoadMailedItems(Mail *mail) if (!result) return; + SQLTransaction trans = CharacterDatabase.BeginTransaction(); do { Field *fields = result->Fetch(); @@ -16867,8 +16886,8 @@ void Player::_LoadMailedItems(Mail *mail) if (!proto) { sLog.outError("Player %u has unknown item_template (ProtoType) in mailed items(GUID: %u template: %u) in mail (%u), deleted.", GetGUIDLow(), item_guid_low, item_template,mail->messageID); - CharacterDatabase.PExecute("DELETE FROM mail_items WHERE item_guid = '%u'", item_guid_low); - CharacterDatabase.PExecute("DELETE FROM item_instance WHERE guid = '%u'", item_guid_low); + trans->PAppend("DELETE FROM mail_items WHERE item_guid = '%u'", item_guid_low); + trans->PAppend("DELETE FROM item_instance WHERE guid = '%u'", item_guid_low); continue; } @@ -16879,12 +16898,14 @@ void Player::_LoadMailedItems(Mail *mail) sLog.outError("Player::_LoadMailedItems - Item in mail (%u) doesn't exist !!!! - item guid: %u, deleted from mail", mail->messageID, item_guid_low); CharacterDatabase.PExecute("DELETE FROM mail_items WHERE item_guid = '%u'", item_guid_low); item->FSetState(ITEM_REMOVED); - item->SaveToDB(); // it also deletes item object ! + item->SaveToDB(trans); // it also deletes item object ! continue; } AddMItem(item); } while (result->NextRow()); + + CharacterDatabase.CommitTransaction(trans); } void Player::_LoadMailInit(QueryResult_AutoPtr resultUnread, QueryResult_AutoPtr resultDelivery) @@ -17737,36 +17758,36 @@ void Player::SaveToDB() ss << uint32(GetByteValue(PLAYER_FIELD_BYTES, 2)); ss << ")"; - CharacterDatabase.BeginTransaction(); + SQLTransaction trans = CharacterDatabase.BeginTransaction(); - CharacterDatabase.Execute(ss.str().c_str()); + trans->Append(ss.str().c_str()); if (m_mailsUpdated) //save mails only when needed - _SaveMail(); - - _SaveBGData(); - _SaveInventory(); - _SaveQuestStatus(); - _SaveDailyQuestStatus(); - _SaveWeeklyQuestStatus(); - _SaveTalents(); - _SaveSpells(); - _SaveSpellCooldowns(); - _SaveActions(); - _SaveAuras(); - _SaveSkills(); - m_achievementMgr.SaveToDB(); - m_reputationMgr.SaveToDB(); - _SaveEquipmentSets(); - GetSession()->SaveTutorialsData(); // changed only while character in game - _SaveGlyphs(); + _SaveMail(trans); + + _SaveBGData(trans); + _SaveInventory(trans); + _SaveQuestStatus(trans); + _SaveDailyQuestStatus(trans); + _SaveWeeklyQuestStatus(trans); + _SaveTalents(trans); + _SaveSpells(trans); + _SaveSpellCooldowns(trans); + _SaveActions(trans); + _SaveAuras(trans); + _SaveSkills(trans); + m_achievementMgr.SaveToDB(trans); + m_reputationMgr.SaveToDB(trans); + _SaveEquipmentSets(trans); + GetSession()->SaveTutorialsData(trans); // changed only while character in game + _SaveGlyphs(trans); // check if stats should only be saved on logout // save stats can be out of transaction if (m_session->isLogingOut() || !sWorld.getConfig(CONFIG_STATS_SAVE_ONLY_ON_LOGOUT)) - _SaveStats(); + _SaveStats(trans); - CharacterDatabase.CommitTransaction(); + CharacterDatabase.CommitTransaction(trans); // save pet (hunter pet level and experience and all type pets health/mana). if (Pet* pet = GetPet()) @@ -17775,37 +17796,37 @@ void Player::SaveToDB() } // fast save function for item/money cheating preventing - save only inventory and money state -void Player::SaveInventoryAndGoldToDB() +void Player::SaveInventoryAndGoldToDB(SQLTransaction& trans) { - _SaveInventory(); - SaveGoldToDB(); + _SaveInventory(trans); + SaveGoldToDB(trans); } -void Player::SaveGoldToDB() +void Player::SaveGoldToDB(SQLTransaction& trans) { - CharacterDatabase.PExecute("UPDATE characters SET money = '%u' WHERE guid = '%u'", GetMoney(), GetGUIDLow()); + trans->PAppend("UPDATE characters SET money = '%u' WHERE guid = '%u'", GetMoney(), GetGUIDLow()); } -void Player::_SaveActions() +void Player::_SaveActions(SQLTransaction& trans) { for (ActionButtonList::iterator itr = m_actionButtons.begin(); itr != m_actionButtons.end();) { switch (itr->second.uState) { case ACTIONBUTTON_NEW: - CharacterDatabase.PExecute("INSERT INTO character_action (guid,spec,button,action,type) VALUES ('%u', '%u', '%u', '%u', '%u')", + trans->PAppend("INSERT INTO character_action (guid,spec,button,action,type) VALUES ('%u', '%u', '%u', '%u', '%u')", GetGUIDLow(), m_activeSpec, (uint32)itr->first, (uint32)itr->second.GetAction(), (uint32)itr->second.GetType()); itr->second.uState = ACTIONBUTTON_UNCHANGED; ++itr; break; case ACTIONBUTTON_CHANGED: - CharacterDatabase.PExecute("UPDATE character_action SET action = '%u', type = '%u' WHERE guid = '%u' AND button = '%u' AND spec = '%u'", + trans->PAppend("UPDATE character_action SET action = '%u', type = '%u' WHERE guid = '%u' AND button = '%u' AND spec = '%u'", (uint32)itr->second.GetAction(), (uint32)itr->second.GetType(), GetGUIDLow(), (uint32)itr->first, m_activeSpec); itr->second.uState = ACTIONBUTTON_UNCHANGED; ++itr; break; case ACTIONBUTTON_DELETED: - CharacterDatabase.PExecute("DELETE FROM character_action WHERE guid = '%u' and button = '%u' and spec = '%u'", GetGUIDLow(), (uint32)itr->first, m_activeSpec); + trans->PAppend("DELETE FROM character_action WHERE guid = '%u' and button = '%u' and spec = '%u'", GetGUIDLow(), (uint32)itr->first, m_activeSpec); m_actionButtons.erase(itr++); break; default: @@ -17815,9 +17836,9 @@ void Player::_SaveActions() } } -void Player::_SaveAuras() +void Player::_SaveAuras(SQLTransaction& trans) { - CharacterDatabase.PExecute("DELETE FROM character_aura WHERE guid = '%u'",GetGUIDLow()); + trans->PAppend("DELETE FROM character_aura WHERE guid = '%u'",GetGUIDLow()); for (AuraMap::const_iterator itr = m_ownedAuras.begin(); itr != m_ownedAuras.end() ; ++itr) { @@ -17847,7 +17868,7 @@ void Player::_SaveAuras() } } - CharacterDatabase.PExecute("INSERT INTO character_aura (guid,caster_guid,spell,effect_mask,recalculate_mask,stackcount,amount0,amount1,amount2,base_amount0,base_amount1,base_amount2,maxduration,remaintime,remaincharges) " + trans->PAppend("INSERT INTO character_aura (guid,caster_guid,spell,effect_mask,recalculate_mask,stackcount,amount0,amount1,amount2,base_amount0,base_amount1,base_amount2,maxduration,remaintime,remaincharges) " "VALUES ('%u', '" UI64FMTD "', '%u', '%u', '%u', '%u', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%u')", GetGUIDLow(), itr->second->GetCasterGUID(), itr->second->GetId(), effMask, recalculateMask, itr->second->GetStackAmount(), damage[0], damage[1], damage[2], baseDamage[0], baseDamage[1], baseDamage[2], @@ -17855,7 +17876,7 @@ void Player::_SaveAuras() } } -void Player::_SaveInventory() +void Player::_SaveInventory(SQLTransaction& trans) { // force items in buyback slots to new state // and remove those that aren't already @@ -17864,8 +17885,8 @@ void Player::_SaveInventory() Item *item = m_items[i]; if (!item || item->GetState() == ITEM_NEW) continue; - CharacterDatabase.PExecute("DELETE FROM character_inventory WHERE item = '%u'", item->GetGUIDLow()); - CharacterDatabase.PExecute("DELETE FROM item_instance WHERE guid = '%u'", item->GetGUIDLow()); + trans->PAppend("DELETE FROM character_inventory WHERE item = '%u'", item->GetGUIDLow()); + trans->PAppend("DELETE FROM item_instance WHERE guid = '%u'", item->GetGUIDLow()); m_items[i]->FSetState(ITEM_NEW); } @@ -17942,25 +17963,25 @@ void Player::_SaveInventory() switch (item->GetState()) { case ITEM_NEW: - CharacterDatabase.PExecute("INSERT INTO character_inventory (guid,bag,slot,item,item_template) VALUES ('%u', '%u', '%u', '%u', '%u')", GetGUIDLow(), bag_guid, item->GetSlot(), item->GetGUIDLow(), item->GetEntry()); + trans->PAppend("INSERT INTO character_inventory (guid,bag,slot,item,item_template) VALUES ('%u', '%u', '%u', '%u', '%u')", GetGUIDLow(), bag_guid, item->GetSlot(), item->GetGUIDLow(), item->GetEntry()); break; case ITEM_CHANGED: - CharacterDatabase.PExecute("DELETE FROM character_inventory WHERE item = '%u'", item->GetGUIDLow()); - CharacterDatabase.PExecute("INSERT INTO character_inventory (guid,bag,slot,item,item_template) VALUES ('%u', '%u', '%u', '%u', '%u')", GetGUIDLow(), bag_guid, item->GetSlot(), item->GetGUIDLow(), item->GetEntry()); + trans->PAppend("DELETE FROM character_inventory WHERE item = '%u'", item->GetGUIDLow()); + trans->PAppend("INSERT INTO character_inventory (guid,bag,slot,item,item_template) VALUES ('%u', '%u', '%u', '%u', '%u')", GetGUIDLow(), bag_guid, item->GetSlot(), item->GetGUIDLow(), item->GetEntry()); break; case ITEM_REMOVED: - CharacterDatabase.PExecute("DELETE FROM character_inventory WHERE item = '%u'", item->GetGUIDLow()); + trans->PAppend("DELETE FROM character_inventory WHERE item = '%u'", item->GetGUIDLow()); break; case ITEM_UNCHANGED: break; } - item->SaveToDB(); // item have unchanged inventory record and can be save standalone + item->SaveToDB(trans); // item have unchanged inventory record and can be save standalone } m_itemUpdateQueue.clear(); } -void Player::_SaveMail() +void Player::_SaveMail(SQLTransaction& trans) { if (!m_mailsLoaded) return; @@ -17970,12 +17991,12 @@ void Player::_SaveMail() Mail *m = (*itr); if (m->state == MAIL_STATE_CHANGED) { - CharacterDatabase.PExecute("UPDATE mail SET has_items = '%u',expire_time = '" UI64FMTD "', deliver_time = '" UI64FMTD "',money = '%u',cod = '%u',checked = '%u' WHERE id = '%u'", + trans->PAppend("UPDATE mail SET has_items = '%u',expire_time = '" UI64FMTD "', deliver_time = '" UI64FMTD "',money = '%u',cod = '%u',checked = '%u' WHERE id = '%u'", m->HasItems() ? 1 : 0, (uint64)m->expire_time, (uint64)m->deliver_time, m->money, m->COD, m->checked, m->messageID); if (m->removedItems.size()) { for (std::vector<uint32>::iterator itr2 = m->removedItems.begin(); itr2 != m->removedItems.end(); ++itr2) - CharacterDatabase.PExecute("DELETE FROM mail_items WHERE item_guid = '%u'", *itr2); + trans->PAppend("DELETE FROM mail_items WHERE item_guid = '%u'", *itr2); m->removedItems.clear(); } m->state = MAIL_STATE_UNCHANGED; @@ -17984,9 +18005,9 @@ void Player::_SaveMail() { if (m->HasItems()) for (std::vector<MailItemInfo>::iterator itr2 = m->items.begin(); itr2 != m->items.end(); ++itr2) - CharacterDatabase.PExecute("DELETE FROM item_instance WHERE guid = '%u'", itr2->item_guid); - CharacterDatabase.PExecute("DELETE FROM mail WHERE id = '%u'", m->messageID); - CharacterDatabase.PExecute("DELETE FROM mail_items WHERE mail_id = '%u'", m->messageID); + trans->PAppend("DELETE FROM item_instance WHERE guid = '%u'", itr2->item_guid); + trans->PAppend("DELETE FROM mail WHERE id = '%u'", m->messageID); + trans->PAppend("DELETE FROM mail_items WHERE mail_id = '%u'", m->messageID); } } @@ -18007,7 +18028,7 @@ void Player::_SaveMail() m_mailsUpdated = false; } -void Player::_SaveQuestStatus() +void Player::_SaveQuestStatus(SQLTransaction& trans) { // we don't need transactions here. for (QuestStatusMap::iterator i = mQuestStatus.begin(); i != mQuestStatus.end(); ++i) @@ -18015,12 +18036,12 @@ void Player::_SaveQuestStatus() switch (i->second.uState) { case QUEST_NEW : - CharacterDatabase.PExecute("INSERT INTO character_queststatus (guid,quest,status,rewarded,explored,timer,mobcount1,mobcount2,mobcount3,mobcount4,itemcount1,itemcount2,itemcount3,itemcount4) " + trans->PAppend("INSERT INTO character_queststatus (guid,quest,status,rewarded,explored,timer,mobcount1,mobcount2,mobcount3,mobcount4,itemcount1,itemcount2,itemcount3,itemcount4) " "VALUES ('%u', '%u', '%u', '%u', '%u', '" UI64FMTD "', '%u', '%u', '%u', '%u', '%u', '%u', '%u', '%u')", GetGUIDLow(), i->first, i->second.m_status, i->second.m_rewarded, i->second.m_explored, uint64(i->second.m_timer / IN_MILLISECONDS+ sWorld.GetGameTime()), i->second.m_creatureOrGOcount[0], i->second.m_creatureOrGOcount[1], i->second.m_creatureOrGOcount[2], i->second.m_creatureOrGOcount[3], i->second.m_itemcount[0], i->second.m_itemcount[1], i->second.m_itemcount[2], i->second.m_itemcount[3]); break; case QUEST_CHANGED : - CharacterDatabase.PExecute("UPDATE character_queststatus SET status = '%u',rewarded = '%u',explored = '%u',timer = '" UI64FMTD "',mobcount1 = '%u',mobcount2 = '%u',mobcount3 = '%u',mobcount4 = '%u',itemcount1 = '%u',itemcount2 = '%u',itemcount3 = '%u',itemcount4 = '%u' WHERE guid = '%u' AND quest = '%u' ", + trans->PAppend("UPDATE character_queststatus SET status = '%u',rewarded = '%u',explored = '%u',timer = '" UI64FMTD "',mobcount1 = '%u',mobcount2 = '%u',mobcount3 = '%u',mobcount4 = '%u',itemcount1 = '%u',itemcount2 = '%u',itemcount3 = '%u',itemcount4 = '%u' WHERE guid = '%u' AND quest = '%u' ", i->second.m_status, i->second.m_rewarded, i->second.m_explored, uint64(i->second.m_timer / IN_MILLISECONDS + sWorld.GetGameTime()), i->second.m_creatureOrGOcount[0], i->second.m_creatureOrGOcount[1], i->second.m_creatureOrGOcount[2], i->second.m_creatureOrGOcount[3], i->second.m_itemcount[0], i->second.m_itemcount[1], i->second.m_itemcount[2], i->second.m_itemcount[3], GetGUIDLow(), i->first); break; case QUEST_UNCHANGED: @@ -18030,7 +18051,7 @@ void Player::_SaveQuestStatus() } } -void Player::_SaveDailyQuestStatus() +void Player::_SaveDailyQuestStatus(SQLTransaction& trans) { if (!m_DailyQuestChanged) return; @@ -18040,32 +18061,32 @@ void Player::_SaveDailyQuestStatus() // save last daily quest time for all quests: we need only mostly reset time for reset check anyway // we don't need transactions here. - CharacterDatabase.PExecute("DELETE FROM character_queststatus_daily WHERE guid = '%u'",GetGUIDLow()); + trans->PAppend("DELETE FROM character_queststatus_daily WHERE guid = '%u'",GetGUIDLow()); for (uint32 quest_daily_idx = 0; quest_daily_idx < PLAYER_MAX_DAILY_QUESTS; ++quest_daily_idx) if (GetUInt32Value(PLAYER_FIELD_DAILY_QUESTS_1+quest_daily_idx)) - CharacterDatabase.PExecute("INSERT INTO character_queststatus_daily (guid,quest,time) VALUES ('%u', '%u','" UI64FMTD "')", + trans->PAppend("INSERT INTO character_queststatus_daily (guid,quest,time) VALUES ('%u', '%u','" UI64FMTD "')", GetGUIDLow(), GetUInt32Value(PLAYER_FIELD_DAILY_QUESTS_1+quest_daily_idx),uint64(m_lastDailyQuestTime)); } -void Player::_SaveWeeklyQuestStatus() +void Player::_SaveWeeklyQuestStatus(SQLTransaction& trans) { if (!m_WeeklyQuestChanged || m_weeklyquests.empty()) return; // we don't need transactions here. - CharacterDatabase.PExecute("DELETE FROM character_queststatus_weekly WHERE guid = '%u'",GetGUIDLow()); + trans->PAppend("DELETE FROM character_queststatus_weekly WHERE guid = '%u'",GetGUIDLow()); for (QuestSet::const_iterator iter = m_weeklyquests.begin(); iter != m_weeklyquests.end(); ++iter) { uint32 quest_id = *iter; - CharacterDatabase.PExecute("INSERT INTO character_queststatus_weekly (guid,quest) VALUES ('%u', '%u')", GetGUIDLow(), quest_id); + trans->PAppend("INSERT INTO character_queststatus_weekly (guid,quest) VALUES ('%u', '%u')", GetGUIDLow(), quest_id); } m_WeeklyQuestChanged = false; } -void Player::_SaveSkills() +void Player::_SaveSkills(SQLTransaction& trans) { // we don't need transactions here. for (SkillStatusMap::iterator itr = mSkillStatus.begin(); itr != mSkillStatus.end();) @@ -18078,7 +18099,7 @@ void Player::_SaveSkills() if (itr->second.uState == SKILL_DELETED) { - CharacterDatabase.PExecute("DELETE FROM character_skills WHERE guid = '%u' AND skill = '%u' ", GetGUIDLow(), itr->first); + trans->PAppend("DELETE FROM character_skills WHERE guid = '%u' AND skill = '%u' ", GetGUIDLow(), itr->first); mSkillStatus.erase(itr++); continue; } @@ -18090,11 +18111,11 @@ void Player::_SaveSkills() switch (itr->second.uState) { case SKILL_NEW: - CharacterDatabase.PExecute("INSERT INTO character_skills (guid, skill, value, max) VALUES ('%u', '%u', '%u', '%u')", + trans->PAppend("INSERT INTO character_skills (guid, skill, value, max) VALUES ('%u', '%u', '%u', '%u')", GetGUIDLow(), itr->first, value, max); break; case SKILL_CHANGED: - CharacterDatabase.PExecute("UPDATE character_skills SET value = '%u',max = '%u'WHERE guid = '%u' AND skill = '%u' ", + trans->PAppend("UPDATE character_skills SET value = '%u',max = '%u'WHERE guid = '%u' AND skill = '%u' ", value, max, GetGUIDLow(), itr->first); break; }; @@ -18104,16 +18125,16 @@ void Player::_SaveSkills() } } -void Player::_SaveSpells() +void Player::_SaveSpells(SQLTransaction& trans) { for (PlayerSpellMap::iterator itr = m_spells.begin(), next = m_spells.begin(); itr != m_spells.end();) { if (itr->second->state == PLAYERSPELL_REMOVED || itr->second->state == PLAYERSPELL_CHANGED) - CharacterDatabase.PExecute("DELETE FROM character_spell WHERE guid = '%u' and spell = '%u'", GetGUIDLow(), itr->first); + trans->PAppend("DELETE FROM character_spell WHERE guid = '%u' and spell = '%u'", GetGUIDLow(), itr->first); // add only changed/new not dependent spells if (!itr->second->dependent && (itr->second->state == PLAYERSPELL_NEW || itr->second->state == PLAYERSPELL_CHANGED)) - CharacterDatabase.PExecute("INSERT INTO character_spell (guid,spell,active,disabled) VALUES ('%u', '%u', '%u', '%u')", GetGUIDLow(), itr->first, itr->second->active ? 1 : 0,itr->second->disabled ? 1 : 0); + trans->PAppend("INSERT INTO character_spell (guid,spell,active,disabled) VALUES ('%u', '%u', '%u', '%u')", GetGUIDLow(), itr->first, itr->second->active ? 1 : 0,itr->second->disabled ? 1 : 0); if (itr->second->state == PLAYERSPELL_REMOVED) { @@ -18131,13 +18152,13 @@ void Player::_SaveSpells() // save player stats -- only for external usage // real stats will be recalculated on player login -void Player::_SaveStats() +void Player::_SaveStats(SQLTransaction& trans) { // check if stat saving is enabled and if char level is high enough if (!sWorld.getConfig(CONFIG_MIN_LEVEL_STAT_SAVE) || getLevel() < sWorld.getConfig(CONFIG_MIN_LEVEL_STAT_SAVE)) return; - CharacterDatabase.PExecute("DELETE FROM character_stats WHERE guid = '%u'", GetGUIDLow()); + trans->PAppend("DELETE FROM character_stats WHERE guid = '%u'", GetGUIDLow()); std::ostringstream ss; ss << "INSERT INTO character_stats (guid, maxhealth, maxpower1, maxpower2, maxpower3, maxpower4, maxpower5, maxpower6, maxpower7, " "strength, agility, stamina, intellect, spirit, armor, resHoly, resFire, resNature, resFrost, resShadow, resArcane, " @@ -18160,7 +18181,7 @@ void Player::_SaveStats() << GetUInt32Value(UNIT_FIELD_ATTACK_POWER) << ", " << GetUInt32Value(UNIT_FIELD_RANGED_ATTACK_POWER) << ", " << GetBaseSpellPowerBonus() << ")"; - CharacterDatabase.Execute(ss.str().c_str()); + trans->Append(ss.str().c_str()); } void Player::outDebugValues() const @@ -19084,18 +19105,18 @@ void Player::RemovePetitionsAndSigns(uint64 guid, uint32 type) CharacterDatabase.PExecute("DELETE FROM petition_sign WHERE playerguid = '%u' AND type = '%u'", GUID_LOPART(guid), type); } - CharacterDatabase.BeginTransaction(); + SQLTransaction trans = CharacterDatabase.BeginTransaction(); if (type == 10) { - CharacterDatabase.PExecute("DELETE FROM petition WHERE ownerguid = '%u'", GUID_LOPART(guid)); - CharacterDatabase.PExecute("DELETE FROM petition_sign WHERE ownerguid = '%u'", GUID_LOPART(guid)); + trans->PAppend("DELETE FROM petition WHERE ownerguid = '%u'", GUID_LOPART(guid)); + trans->PAppend("DELETE FROM petition_sign WHERE ownerguid = '%u'", GUID_LOPART(guid)); } else { - CharacterDatabase.PExecute("DELETE FROM petition WHERE ownerguid = '%u' AND type = '%u'", GUID_LOPART(guid), type); - CharacterDatabase.PExecute("DELETE FROM petition_sign WHERE ownerguid = '%u' AND type = '%u'", GUID_LOPART(guid), type); + trans->PAppend("DELETE FROM petition WHERE ownerguid = '%u' AND type = '%u'", GUID_LOPART(guid), type); + trans->PAppend("DELETE FROM petition_sign WHERE ownerguid = '%u' AND type = '%u'", GUID_LOPART(guid), type); } - CharacterDatabase.CommitTransaction(); + CharacterDatabase.CommitTransaction(trans); } void Player::LeaveAllArenaTeams(uint64 guid) @@ -21507,13 +21528,14 @@ void Player::AutoUnequipOffhandIfNeed(bool force /*= false*/) else { MoveItemFromInventory(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND, true); - CharacterDatabase.BeginTransaction(); - offItem->DeleteFromInventoryDB(); // deletes item from character's inventory - offItem->SaveToDB(); // recursive and not have transaction guard into self, item not in inventory and can be save standalone - CharacterDatabase.CommitTransaction(); - + SQLTransaction trans = CharacterDatabase.BeginTransaction(); + offItem->DeleteFromInventoryDB(trans); // deletes item from character's inventory + offItem->SaveToDB(trans); // recursive and not have transaction guard into self, item not in inventory and can be save standalone + std::string subject = GetSession()->GetTrinityString(LANG_NOT_EQUIPPED_ITEM); - MailDraft(subject, "There were problems with equipping one or several items").AddItem(offItem).SendMailTo(this, MailSender(this, MAIL_STATIONERY_GM), MAIL_CHECK_MASK_COPIED); + MailDraft(subject, "There were problems with equipping one or several items").AddItem(offItem).SendMailTo(trans, this, MailSender(this, MAIL_STATIONERY_GM), MAIL_CHECK_MASK_COPIED); + + CharacterDatabase.CommitTransaction(trans); } } @@ -23519,7 +23541,7 @@ void Player::SetEquipmentSet(uint32 index, EquipmentSet eqset) eqslot.state = old_state == EQUIPMENT_SET_NEW ? EQUIPMENT_SET_NEW : EQUIPMENT_SET_CHANGED; } -void Player::_SaveEquipmentSets() +void Player::_SaveEquipmentSets(SQLTransaction& trans) { for (EquipmentSets::iterator itr = m_EquipmentSets.begin(); itr != m_EquipmentSets.end();) { @@ -23533,7 +23555,7 @@ void Player::_SaveEquipmentSets() case EQUIPMENT_SET_CHANGED: CharacterDatabase.escape_string(eqset.Name); CharacterDatabase.escape_string(eqset.IconName); - CharacterDatabase.PExecute("UPDATE character_equipmentsets SET name='%s', iconname='%s', item0='%u', item1='%u', item2='%u', item3='%u', item4='%u', item5='%u', item6='%u', item7='%u', item8='%u', item9='%u', item10='%u', item11='%u', item12='%u', item13='%u', item14='%u', item15='%u', item16='%u', item17='%u', item18='%u' WHERE guid='%u' AND setguid='"UI64FMTD"' AND setindex='%u'", + trans->PAppend("UPDATE character_equipmentsets SET name='%s', iconname='%s', item0='%u', item1='%u', item2='%u', item3='%u', item4='%u', item5='%u', item6='%u', item7='%u', item8='%u', item9='%u', item10='%u', item11='%u', item12='%u', item13='%u', item14='%u', item15='%u', item16='%u', item17='%u', item18='%u' WHERE guid='%u' AND setguid='"UI64FMTD"' AND setindex='%u'", eqset.Name.c_str(), eqset.IconName.c_str(), eqset.Items[0], eqset.Items[1], eqset.Items[2], eqset.Items[3], eqset.Items[4], eqset.Items[5], eqset.Items[6], eqset.Items[7], eqset.Items[8], eqset.Items[9], eqset.Items[10], eqset.Items[11], eqset.Items[12], eqset.Items[13], eqset.Items[14], eqset.Items[15], eqset.Items[16], eqset.Items[17], eqset.Items[18], GetGUIDLow(), eqset.Guid, index); eqset.state = EQUIPMENT_SET_UNCHANGED; @@ -23542,27 +23564,27 @@ void Player::_SaveEquipmentSets() case EQUIPMENT_SET_NEW: CharacterDatabase.escape_string(eqset.Name); CharacterDatabase.escape_string(eqset.IconName); - CharacterDatabase.PExecute("INSERT INTO character_equipmentsets VALUES ('%u', '"UI64FMTD"', '%u', '%s', '%s', '%u', '%u', '%u', '%u', '%u', '%u', '%u', '%u', '%u', '%u', '%u', '%u', '%u', '%u', '%u', '%u', '%u', '%u', '%u')", + trans->PAppend("INSERT INTO character_equipmentsets VALUES ('%u', '"UI64FMTD"', '%u', '%s', '%s', '%u', '%u', '%u', '%u', '%u', '%u', '%u', '%u', '%u', '%u', '%u', '%u', '%u', '%u', '%u', '%u', '%u', '%u', '%u')", GetGUIDLow(), eqset.Guid, index, eqset.Name.c_str(), eqset.IconName.c_str(), eqset.Items[0], eqset.Items[1], eqset.Items[2], eqset.Items[3], eqset.Items[4], eqset.Items[5], eqset.Items[6], eqset.Items[7], eqset.Items[8], eqset.Items[9], eqset.Items[10], eqset.Items[11], eqset.Items[12], eqset.Items[13], eqset.Items[14], eqset.Items[15], eqset.Items[16], eqset.Items[17], eqset.Items[18]); eqset.state = EQUIPMENT_SET_UNCHANGED; ++itr; break; case EQUIPMENT_SET_DELETED: - CharacterDatabase.PExecute("DELETE FROM character_equipmentsets WHERE setguid="UI64FMTD, eqset.Guid); + trans->PAppend("DELETE FROM character_equipmentsets WHERE setguid="UI64FMTD, eqset.Guid); m_EquipmentSets.erase(itr++); break; } } } -void Player::_SaveBGData() +void Player::_SaveBGData(SQLTransaction& trans) { - CharacterDatabase.PExecute("DELETE FROM character_battleground_data WHERE guid='%u'", GetGUIDLow()); + trans->PAppend("DELETE FROM character_battleground_data WHERE guid='%u'", GetGUIDLow()); if (m_bgData.bgInstanceID) { /* guid, bgInstanceID, bgTeam, x, y, z, o, map, taxi[0], taxi[1], mountSpell */ - CharacterDatabase.PExecute("INSERT INTO character_battleground_data VALUES ('%u', '%u', '%u', '%f', '%f', '%f', '%f', '%u', '%u', '%u', '%u')", + trans->PAppend("INSERT INTO character_battleground_data VALUES ('%u', '%u', '%u', '%f', '%f', '%f', '%f', '%u', '%u', '%u', '%u')", GetGUIDLow(), m_bgData.bgInstanceID, m_bgData.bgTeam, m_bgData.joinPos.GetPositionX(), m_bgData.joinPos.GetPositionY(), m_bgData.joinPos.GetPositionZ(), m_bgData.joinPos.GetOrientation(), m_bgData.joinPos.GetMapId(), m_bgData.taxiPath[0], m_bgData.taxiPath[1], m_bgData.mountSpell); } @@ -23641,12 +23663,12 @@ void Player::_LoadGlyphs(QueryResult_AutoPtr result) } while (result->NextRow()); } -void Player::_SaveGlyphs() +void Player::_SaveGlyphs(SQLTransaction& trans) { - CharacterDatabase.PExecute("DELETE FROM character_glyphs WHERE guid='%u'",GetGUIDLow()); + trans->PAppend("DELETE FROM character_glyphs WHERE guid='%u'",GetGUIDLow()); for (uint8 spec = 0; spec < m_specsCount; ++spec) { - CharacterDatabase.PExecute("INSERT INTO character_glyphs VALUES('%u', '%u', '%u', '%u', '%u', '%u', '%u', '%u')", + trans->PAppend("INSERT INTO character_glyphs VALUES('%u', '%u', '%u', '%u', '%u', '%u', '%u', '%u')", GetGUIDLow(), spec, m_Glyphs[spec][0], m_Glyphs[spec][1], m_Glyphs[spec][2], m_Glyphs[spec][3], m_Glyphs[spec][4], m_Glyphs[spec][5]); } } @@ -23666,17 +23688,17 @@ void Player::_LoadTalents(QueryResult_AutoPtr result) } } -void Player::_SaveTalents() +void Player::_SaveTalents(SQLTransaction& trans) { for (uint8 i = 0; i < MAX_TALENT_SPECS; ++i) { for (PlayerTalentMap::iterator itr = m_talents[i]->begin(); itr != m_talents[i]->end();) { if (itr->second->state == PLAYERSPELL_REMOVED || itr->second->state == PLAYERSPELL_CHANGED) - CharacterDatabase.PExecute("DELETE FROM character_talent WHERE guid = '%u' and spell = '%u' and spec = '%u'", GetGUIDLow(), itr->first, itr->second->spec); + trans->PAppend("DELETE FROM character_talent WHERE guid = '%u' and spell = '%u' and spec = '%u'", GetGUIDLow(), itr->first, itr->second->spec); if (itr->second->state == PLAYERSPELL_NEW || itr->second->state == PLAYERSPELL_CHANGED) - CharacterDatabase.PExecute("INSERT INTO character_talent (guid,spell,spec) VALUES ('%u', '%u', '%u')", GetGUIDLow(), itr->first, itr->second->spec); + trans->PAppend("INSERT INTO character_talent (guid,spell,spec) VALUES ('%u', '%u', '%u')", GetGUIDLow(), itr->first, itr->second->spec); if (itr->second->state == PLAYERSPELL_REMOVED) { @@ -23701,23 +23723,26 @@ void Player::UpdateSpecCount(uint8 count) if (m_activeSpec >= count) ActivateSpec(0); + SQLTransaction trans = CharacterDatabase.BeginTransaction(); + // Copy spec data if (count > curCount) { - _SaveActions(); // make sure the button list is cleaned up + _SaveActions(trans); // make sure the button list is cleaned up for (ActionButtonList::iterator itr = m_actionButtons.begin(); itr != m_actionButtons.end(); ++itr) - CharacterDatabase.PExecute("INSERT INTO character_action (guid,button,action,type,spec) VALUES ('%u', '%u', '%u', '%u', '%u')", + trans->PAppend("INSERT INTO character_action (guid,button,action,type,spec) VALUES ('%u', '%u', '%u', '%u', '%u')", GetGUIDLow(), uint32(itr->first), uint32(itr->second.GetAction()), uint32(itr->second.GetType()), 1); } // Delete spec data for removed spec. else if (count < curCount) { - _SaveActions(); - CharacterDatabase.PExecute("DELETE FROM character_action WHERE spec<>'%u' AND guid='%u'",m_activeSpec, GetGUIDLow()); + _SaveActions(trans); + trans->PAppend("DELETE FROM character_action WHERE spec<>'%u' AND guid='%u'",m_activeSpec, GetGUIDLow()); m_activeSpec = 0; } - + + CharacterDatabase.CommitTransaction(trans); SetSpecsCount(count); @@ -23740,7 +23765,9 @@ void Player::ActivateSpec(uint8 spec) if (IsNonMeleeSpellCasted(false)) InterruptNonMeleeSpells(false); - _SaveActions(); + SQLTransaction trans = CharacterDatabase.BeginTransaction(); + _SaveActions(trans); + CharacterDatabase.CommitTransaction(trans); UnsummonPetTemporaryIfAny(); ClearComboPointHolders(); diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index 24233681a23..26acb7266c0 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -1422,8 +1422,9 @@ class Player : public Unit, public GridObject<Player> /*********************************************************/ void SaveToDB(); - void SaveInventoryAndGoldToDB(); // fast save function for item/money cheating preventing - void SaveGoldToDB(); + void SaveInventoryAndGoldToDB(SQLTransaction& trans); // fast save function for item/money cheating preventing + void SaveGoldToDB(SQLTransaction& trans); + static void SetUInt32ValueInArray(Tokens& data,uint16 index, uint32 value); static void SetFloatValueInArray(Tokens& data,uint16 index, float value); static void Customize(uint64 guid, uint8 gender, uint8 skin, uint8 face, uint8 hairStyle, uint8 hairColor, uint8 facialHair); @@ -1617,7 +1618,7 @@ class Player : public Unit, public GridObject<Player> void RemoveArenaSpellCooldowns(); void RemoveAllSpellCooldown(); void _LoadSpellCooldowns(QueryResult_AutoPtr result); - void _SaveSpellCooldowns(); + void _SaveSpellCooldowns(SQLTransaction& trans); void SetLastPotionId(uint32 item_id) { m_lastPotionId = item_id; } void UpdatePotionCooldown(Spell* spell = NULL); @@ -2428,20 +2429,20 @@ class Player : public Unit, public GridObject<Player> /*** SAVE SYSTEM ***/ /*********************************************************/ - void _SaveActions(); - void _SaveAuras(); - void _SaveInventory(); - void _SaveMail(); - void _SaveQuestStatus(); - void _SaveDailyQuestStatus(); - void _SaveWeeklyQuestStatus(); - void _SaveSkills(); - void _SaveSpells(); - void _SaveEquipmentSets(); - void _SaveBGData(); - void _SaveGlyphs(); - void _SaveTalents(); - void _SaveStats(); + void _SaveActions(SQLTransaction& trans); + void _SaveAuras(SQLTransaction& trans); + void _SaveInventory(SQLTransaction& trans); + void _SaveMail(SQLTransaction& trans); + void _SaveQuestStatus(SQLTransaction& trans); + void _SaveDailyQuestStatus(SQLTransaction& trans); + void _SaveWeeklyQuestStatus(SQLTransaction& trans); + void _SaveSkills(SQLTransaction& trans); + void _SaveSpells(SQLTransaction& trans); + void _SaveEquipmentSets(SQLTransaction& trans); + void _SaveBGData(SQLTransaction& trans); + void _SaveGlyphs(SQLTransaction& trans); + void _SaveTalents(SQLTransaction& trans); + void _SaveStats(SQLTransaction& trans); void _SetCreateBits(UpdateMask *updateMask, Player *target) const; void _SetUpdateBits(UpdateMask *updateMask, Player *target) const; diff --git a/src/server/game/Events/GameEventMgr.cpp b/src/server/game/Events/GameEventMgr.cpp index 4f9fc0f5b9a..f94f61063ca 100644 --- a/src/server/game/Events/GameEventMgr.cpp +++ b/src/server/game/Events/GameEventMgr.cpp @@ -181,10 +181,10 @@ void GameEventMgr::StopEvent(uint16 event_id, bool overwrite) std::map<uint32 /*condition id*/, GameEventFinishCondition>::iterator itr; for (itr = mGameEvent[event_id].conditions.begin(); itr != mGameEvent[event_id].conditions.end(); ++itr) itr->second.done = 0; - CharacterDatabase.BeginTransaction(); - CharacterDatabase.PExecute("DELETE FROM game_event_save WHERE event_id = '%u'",event_id); - CharacterDatabase.PExecute("DELETE FROM game_event_condition_save WHERE event_id = '%u'",event_id); - CharacterDatabase.CommitTransaction(); + SQLTransaction trans = CharacterDatabase.BeginTransaction(); + trans->PAppend("DELETE FROM game_event_save WHERE event_id = '%u'",event_id); + trans->PAppend("DELETE FROM game_event_condition_save WHERE event_id = '%u'",event_id); + CharacterDatabase.CommitTransaction(trans); } } } @@ -1627,10 +1627,10 @@ void GameEventMgr::HandleQuestComplete(uint32 quest_id) if (citr->second.done > citr->second.reqNum) citr->second.done = citr->second.reqNum; // save the change to db - CharacterDatabase.BeginTransaction(); - CharacterDatabase.PExecute("DELETE FROM game_event_condition_save WHERE event_id = '%u' AND condition_id = '%u'",event_id,condition); - CharacterDatabase.PExecute("INSERT INTO game_event_condition_save (event_id, condition_id, done) VALUES (%u,%u,%f)",event_id,condition,citr->second.done); - CharacterDatabase.CommitTransaction(); + SQLTransaction trans = CharacterDatabase.BeginTransaction(); + trans->PAppend("DELETE FROM game_event_condition_save WHERE event_id = '%u' AND condition_id = '%u'",event_id,condition); + trans->PAppend("INSERT INTO game_event_condition_save (event_id, condition_id, done) VALUES (%u,%u,%f)",event_id,condition,citr->second.done); + CharacterDatabase.CommitTransaction(trans); // check if all conditions are met, if so, update the event state if (CheckOneGameEventConditions(event_id)) { @@ -1663,13 +1663,13 @@ bool GameEventMgr::CheckOneGameEventConditions(uint16 event_id) void GameEventMgr::SaveWorldEventStateToDB(uint16 event_id) { - CharacterDatabase.BeginTransaction(); - CharacterDatabase.PExecute("DELETE FROM game_event_save WHERE event_id = '%u'",event_id); + SQLTransaction trans = CharacterDatabase.BeginTransaction(); + trans->PAppend("DELETE FROM game_event_save WHERE event_id = '%u'",event_id); if (mGameEvent[event_id].nextstart) - CharacterDatabase.PExecute("INSERT INTO game_event_save (event_id, state, next_start) VALUES ('%u','%u',FROM_UNIXTIME("UI64FMTD"))",event_id,mGameEvent[event_id].state,(uint64)(mGameEvent[event_id].nextstart)); + trans->PAppend("INSERT INTO game_event_save (event_id, state, next_start) VALUES ('%u','%u',FROM_UNIXTIME("UI64FMTD"))",event_id,mGameEvent[event_id].state,(uint64)(mGameEvent[event_id].nextstart)); else - CharacterDatabase.PExecute("INSERT INTO game_event_save (event_id, state, next_start) VALUES ('%u','%u','0000-00-00 00:00:00')",event_id,mGameEvent[event_id].state); - CharacterDatabase.CommitTransaction(); + trans->PAppend("INSERT INTO game_event_save (event_id, state, next_start) VALUES ('%u','%u','0000-00-00 00:00:00')",event_id,mGameEvent[event_id].state); + CharacterDatabase.CommitTransaction(trans); } void GameEventMgr::HandleWorldEventGossip(Player *plr, Creature *c) diff --git a/src/server/game/Globals/ObjectAccessor.cpp b/src/server/game/Globals/ObjectAccessor.cpp index fdb13637263..c781fe86916 100644 --- a/src/server/game/Globals/ObjectAccessor.cpp +++ b/src/server/game/Globals/ObjectAccessor.cpp @@ -295,7 +295,9 @@ Corpse* ObjectAccessor::ConvertCorpseForPlayer(uint64 player_guid, bool /*insign // map->Remove(corpse, false); // remove corpse from DB - corpse->DeleteFromDB(); + SQLTransaction trans = WorldDatabase.BeginTransaction(); + corpse->DeleteFromDB(trans); + WorldDatabase.CommitTransaction(trans); // we don't want bones to save some cpu.. :) delete corpse; diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index e60fc55250b..247cbdeb6b1 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -9040,9 +9040,10 @@ void ObjectMgr::_AddOrUpdateGMTicket(GM_Ticket &ticket) ss << ticket.closed << "', '"; ss << ticket.assignedToGM << "', '"; ss << comment << "');"; - CharacterDatabase.BeginTransaction(); - CharacterDatabase.Execute(ss.str().c_str()); - CharacterDatabase.CommitTransaction(); + + SQLTransaction trans = CharacterDatabase.BeginTransaction(); + trans->Append(ss.str().c_str()); + CharacterDatabase.CommitTransaction(trans); } void ObjectMgr::RemoveGMTicket(GM_Ticket *ticket, int64 source, bool permanently) diff --git a/src/server/game/Groups/Group.cpp b/src/server/game/Groups/Group.cpp index 837f7d3ad77..7a8ffb061b5 100644 --- a/src/server/game/Groups/Group.cpp +++ b/src/server/game/Groups/Group.cpp @@ -116,20 +116,19 @@ bool Group::Create(const uint64 &guid, const char * name) Player::ConvertInstancesToGroup(leader, this, guid); + if (!AddMember(guid, name)) + return false; + // store group in database - CharacterDatabase.BeginTransaction(); - CharacterDatabase.PExecute("DELETE FROM groups WHERE guid ='%u'", lowguid); - CharacterDatabase.PExecute("DELETE FROM group_member WHERE guid ='%u'", lowguid); - CharacterDatabase.PExecute("INSERT INTO groups (guid,leaderGuid,lootMethod,looterGuid,lootThreshold,icon1,icon2,icon3,icon4,icon5,icon6,icon7,icon8,groupType,difficulty,raiddifficulty) " + SQLTransaction trans = CharacterDatabase.BeginTransaction(); + trans->PAppend("DELETE FROM groups WHERE guid ='%u'", lowguid); + trans->PAppend("DELETE FROM group_member WHERE guid ='%u'", lowguid); + trans->PAppend("INSERT INTO groups (guid,leaderGuid,lootMethod,looterGuid,lootThreshold,icon1,icon2,icon3,icon4,icon5,icon6,icon7,icon8,groupType,difficulty,raiddifficulty) " "VALUES ('%u','%u','%u','%u','%u','" UI64FMTD "','" UI64FMTD "','" UI64FMTD "','" UI64FMTD "','" UI64FMTD "','" UI64FMTD "','" UI64FMTD "','" UI64FMTD "','%u','%u','%u')", lowguid, GUID_LOPART(m_leaderGuid), uint32(m_lootMethod), GUID_LOPART(m_looterGuid), uint32(m_lootThreshold), m_targetIcons[0], m_targetIcons[1], m_targetIcons[2], m_targetIcons[3], m_targetIcons[4], m_targetIcons[5], m_targetIcons[6], m_targetIcons[7], uint8(m_groupType), uint32(m_dungeonDifficulty), m_raidDifficulty); - if (!AddMember(guid, name)) - { - CharacterDatabase.RollbackTransaction(); - return false; - } - CharacterDatabase.CommitTransaction(); + + CharacterDatabase.CommitTransaction(trans); } else if (!AddMember(guid, name)) return false; @@ -497,10 +496,10 @@ void Group::Disband(bool hideDestroy) if (!isBGGroup()) { uint32 lowguid = GUID_LOPART(m_guid); - CharacterDatabase.BeginTransaction(); - CharacterDatabase.PExecute("DELETE FROM groups WHERE guid=%u", lowguid); - CharacterDatabase.PExecute("DELETE FROM group_member WHERE guid=%u", lowguid); - CharacterDatabase.CommitTransaction(); + SQLTransaction trans = CharacterDatabase.BeginTransaction(); + trans->PAppend("DELETE FROM groups WHERE guid=%u", lowguid); + trans->PAppend("DELETE FROM group_member WHERE guid=%u", lowguid); + CharacterDatabase.CommitTransaction(trans); ResetInstances(INSTANCE_RESET_GROUP_DISBAND, false, NULL); ResetInstances(INSTANCE_RESET_GROUP_DISBAND, true, NULL); } @@ -1334,14 +1333,14 @@ void Group::_setLeader(const uint64 &guid) if (!isBGGroup()) { // TODO: set a time limit to have this function run rarely cause it can be slow - CharacterDatabase.BeginTransaction(); + SQLTransaction trans = CharacterDatabase.BeginTransaction(); // update the group's bound instances when changing leaders // remove all permanent binds from the group // in the DB also remove solo binds that will be replaced with permbinds // from the new leader - CharacterDatabase.PExecute( + trans->PAppend( "DELETE FROM group_instance WHERE guid=%u AND (permanent = 1 OR " "instance IN (SELECT instance FROM character_instance WHERE guid = '%u')" ")", GUID_LOPART(m_guid), GUID_LOPART(slot->guid) @@ -1371,8 +1370,8 @@ void Group::_setLeader(const uint64 &guid) Player::ConvertInstancesToGroup(player, this, slot->guid); // update the group leader - CharacterDatabase.PExecute("UPDATE groups SET leaderGuid='%u' WHERE guid='%u'", GUID_LOPART(slot->guid), GUID_LOPART(m_guid)); - CharacterDatabase.CommitTransaction(); + trans->PAppend("UPDATE groups SET leaderGuid='%u' WHERE guid='%u'", GUID_LOPART(slot->guid), GUID_LOPART(m_guid)); + CharacterDatabase.CommitTransaction(trans); } m_leaderGuid = slot->guid; diff --git a/src/server/game/Guilds/Guild.cpp b/src/server/game/Guilds/Guild.cpp index 6e59773b57a..0617e66ef7b 100644 --- a/src/server/game/Guilds/Guild.cpp +++ b/src/server/game/Guilds/Guild.cpp @@ -88,13 +88,13 @@ bool Guild::Create(Player* leader, std::string gname) CharacterDatabase.escape_string(dbGINFO); CharacterDatabase.escape_string(dbMOTD); - CharacterDatabase.BeginTransaction(); + SQLTransaction trans = CharacterDatabase.BeginTransaction(); // CharacterDatabase.PExecute("DELETE FROM guild WHERE guildid='%u'", Id); - MAX(guildid)+1 not exist - CharacterDatabase.PExecute("DELETE FROM guild_member WHERE guildid='%u'", m_Id); - CharacterDatabase.PExecute("INSERT INTO guild (guildid,name,leaderguid,info,motd,createdate,EmblemStyle,EmblemColor,BorderStyle,BorderColor,BackgroundColor,BankMoney) " + trans->PAppend("DELETE FROM guild_member WHERE guildid='%u'", m_Id); + trans->PAppend("INSERT INTO guild (guildid,name,leaderguid,info,motd,createdate,EmblemStyle,EmblemColor,BorderStyle,BorderColor,BackgroundColor,BankMoney) " "VALUES('%u','%s','%u', '%s', '%s', UNIX_TIMESTAMP(NOW()),'%u','%u','%u','%u','%u','" UI64FMTD "')", m_Id, gname.c_str(), GUID_LOPART(m_LeaderGuid), dbGINFO.c_str(), dbMOTD.c_str(), m_EmblemStyle, m_EmblemColor, m_BorderStyle, m_BorderColor, m_BackgroundColor, m_GuildBankMoney); - CharacterDatabase.CommitTransaction(); + CharacterDatabase.CommitTransaction(trans); CreateDefaultGuildRanks(lSession->GetSessionDbLocaleIndex()); @@ -335,16 +335,16 @@ bool Guild::LoadRanksFromDB(QueryResult_AutoPtr guildRanksResult) if (broken_ranks) { sLog.outError("Guild %u has broken `guild_rank` data, repairing...", m_Id); - CharacterDatabase.BeginTransaction(); - CharacterDatabase.PExecute("DELETE FROM guild_rank WHERE guildid='%u'", m_Id); + SQLTransaction trans = CharacterDatabase.BeginTransaction(); + trans->PAppend("DELETE FROM guild_rank WHERE guildid='%u'", m_Id); for (size_t i = 0; i < m_Ranks.size(); ++i) { std::string name = m_Ranks[i].Name; uint32 rights = m_Ranks[i].Rights; CharacterDatabase.escape_string(name); - CharacterDatabase.PExecute("INSERT INTO guild_rank (guildid,rid,rname,rights) VALUES ('%u', '%u', '%s', '%u')", m_Id, uint32(i), name.c_str(), rights); + trans->PAppend("INSERT INTO guild_rank (guildid,rid,rname,rights) VALUES ('%u', '%u', '%s', '%u')", m_Id, uint32(i), name.c_str(), rights); } - CharacterDatabase.CommitTransaction(); + CharacterDatabase.CommitTransaction(trans); } return true; @@ -710,19 +710,19 @@ void Guild::Disband() DelMember(MAKE_NEW_GUID(itr->first, 0, HIGHGUID_PLAYER), true); } - CharacterDatabase.BeginTransaction(); - CharacterDatabase.PExecute("DELETE FROM guild WHERE guildid = '%u'", m_Id); - CharacterDatabase.PExecute("DELETE FROM guild_rank WHERE guildid = '%u'", m_Id); - CharacterDatabase.PExecute("DELETE FROM guild_bank_tab WHERE guildid = '%u'", m_Id); + SQLTransaction trans = CharacterDatabase.BeginTransaction(); + trans->PAppend("DELETE FROM guild WHERE guildid = '%u'", m_Id); + trans->PAppend("DELETE FROM guild_rank WHERE guildid = '%u'", m_Id); + trans->PAppend("DELETE FROM guild_bank_tab WHERE guildid = '%u'", m_Id); //Free bank tab used memory and delete items stored in them DeleteGuildBankItems(true); - CharacterDatabase.PExecute("DELETE FROM guild_bank_item WHERE guildid = '%u'", m_Id); - CharacterDatabase.PExecute("DELETE FROM guild_bank_right WHERE guildid = '%u'", m_Id); - CharacterDatabase.PExecute("DELETE FROM guild_bank_eventlog WHERE guildid = '%u'", m_Id); - CharacterDatabase.PExecute("DELETE FROM guild_eventlog WHERE guildid = '%u'", m_Id); - CharacterDatabase.CommitTransaction(); + trans->PAppend("DELETE FROM guild_bank_item WHERE guildid = '%u'", m_Id); + trans->PAppend("DELETE FROM guild_bank_right WHERE guildid = '%u'", m_Id); + trans->PAppend("DELETE FROM guild_bank_eventlog WHERE guildid = '%u'", m_Id); + trans->PAppend("DELETE FROM guild_eventlog WHERE guildid = '%u'", m_Id); + CharacterDatabase.CommitTransaction(trans); sObjectMgr.RemoveGuild(m_Id); } @@ -1093,10 +1093,10 @@ void Guild::CreateNewBankTab() uint32 tabId = GetPurchasedTabs(); // next free id m_TabListMap.push_back(new GuildBankTab); - CharacterDatabase.BeginTransaction(); - CharacterDatabase.PExecute("DELETE FROM guild_bank_tab WHERE guildid='%u' AND TabId='%u'", m_Id, tabId); - CharacterDatabase.PExecute("INSERT INTO guild_bank_tab (guildid,TabId) VALUES ('%u','%u')", m_Id, tabId); - CharacterDatabase.CommitTransaction(); + SQLTransaction trans = CharacterDatabase.BeginTransaction(); + trans->PAppend("DELETE FROM guild_bank_tab WHERE guildid='%u' AND TabId='%u'", m_Id, tabId); + trans->PAppend("INSERT INTO guild_bank_tab (guildid,TabId) VALUES ('%u','%u')", m_Id, tabId); + CharacterDatabase.CommitTransaction(trans); } void Guild::SetGuildBankTabInfo(uint8 TabId, std::string Name, std::string Icon) @@ -1212,14 +1212,14 @@ void Guild::SendMoneyInfo(WorldSession *session, uint32 LowGuid) sLog.outDebug("WORLD: Sent MSG_GUILD_BANK_MONEY_WITHDRAWN"); } -bool Guild::MemberMoneyWithdraw(uint32 amount, uint32 LowGuid) +bool Guild::MemberMoneyWithdraw(uint32 amount, uint32 LowGuid, SQLTransaction& trans) { uint32 MoneyWithDrawRight = GetMemberMoneyWithdrawRem(LowGuid); if (MoneyWithDrawRight < amount || GetGuildBankMoney() < amount) return false; - SetBankMoney(GetGuildBankMoney()-amount); + SetBankMoney(GetGuildBankMoney()-amount, trans); if (MoneyWithDrawRight < WITHDRAW_MONEY_UNLIMITED) { @@ -1227,25 +1227,25 @@ bool Guild::MemberMoneyWithdraw(uint32 amount, uint32 LowGuid) if (itr == members.end()) return false; itr->second.BankRemMoney -= amount; - CharacterDatabase.PExecute("UPDATE guild_member SET BankRemMoney='%u' WHERE guildid='%u' AND guid='%u'", + trans->PAppend("UPDATE guild_member SET BankRemMoney='%u' WHERE guildid='%u' AND guid='%u'", itr->second.BankRemMoney, m_Id, LowGuid); } return true; } -void Guild::SetBankMoney(int64 money) +void Guild::SetBankMoney(int64 money, SQLTransaction& trans) { if (money < 0) // I don't know how this happens, it does!! money = 0; m_GuildBankMoney = money; - CharacterDatabase.PExecute("UPDATE guild SET BankMoney='" UI64FMTD "' WHERE guildid='%u'", money, m_Id); + trans->PAppend("UPDATE guild SET BankMoney='" UI64FMTD "' WHERE guildid='%u'", money, m_Id); } // ************************************************* // Item per day and money per day related -bool Guild::MemberItemWithdraw(uint8 TabId, uint32 LowGuid) +bool Guild::MemberItemWithdraw(uint8 TabId, uint32 LowGuid, SQLTransaction& trans) { uint32 SlotsWithDrawRight = GetMemberSlotWithdrawRem(LowGuid, TabId); @@ -1258,7 +1258,7 @@ bool Guild::MemberItemWithdraw(uint8 TabId, uint32 LowGuid) if (itr == members.end()) return false; --itr->second.BankRemSlotsTab[TabId]; - CharacterDatabase.PExecute("UPDATE guild_member SET BankRemSlotsTab%u='%u' WHERE guildid='%u' AND guid='%u'", + trans->PAppend("UPDATE guild_member SET BankRemSlotsTab%u='%u' WHERE guildid='%u' AND guid='%u'", uint32(TabId), itr->second.BankRemSlotsTab[TabId], m_Id, LowGuid); } return true; @@ -1552,7 +1552,7 @@ void Guild::DisplayGuildBankLogs(WorldSession *session, uint8 TabId) sLog.outDebug("WORLD: Sent (MSG_GUILD_BANK_LOG_QUERY)"); } -void Guild::LogBankEvent(uint8 EventType, uint8 TabId, uint32 PlayerGuidLow, uint32 ItemOrMoney, uint8 ItemStackCount, uint8 DestTabId) +void Guild::LogBankEvent(SQLTransaction& trans, uint8 EventType, uint8 TabId, uint32 PlayerGuidLow, uint32 ItemOrMoney, uint8 ItemStackCount, uint8 DestTabId) { //create Event GuildBankEventLogEntry NewEvent; @@ -1587,9 +1587,9 @@ void Guild::LogBankEvent(uint8 EventType, uint8 TabId, uint32 PlayerGuidLow, uin } //save event to database - CharacterDatabase.PExecute("DELETE FROM guild_bank_eventlog WHERE guildid='%u' AND LogGuid='%u' AND TabId='%u'", m_Id, currentLogGuid, currentTabId); + trans->PAppend("DELETE FROM guild_bank_eventlog WHERE guildid='%u' AND LogGuid='%u' AND TabId='%u'", m_Id, currentLogGuid, currentTabId); - CharacterDatabase.PExecute("INSERT INTO guild_bank_eventlog (guildid,LogGuid,TabId,EventType,PlayerGuid,ItemOrMoney,ItemStackCount,DestTabId,TimeStamp) VALUES ('%u','%u','%u','%u','%u','%u','%u','%u','" UI64FMTD "')", + trans->PAppend("INSERT INTO guild_bank_eventlog (guildid,LogGuid,TabId,EventType,PlayerGuid,ItemOrMoney,ItemStackCount,DestTabId,TimeStamp) VALUES ('%u','%u','%u','%u','%u','%u','%u','%u','" UI64FMTD "')", m_Id, currentLogGuid, currentTabId, uint32(NewEvent.EventType), NewEvent.PlayerGuid, NewEvent.ItemOrMoney, uint32(NewEvent.ItemStackCount), uint32(NewEvent.DestTabId), NewEvent.TimeStamp); } @@ -1637,7 +1637,7 @@ void Guild::AppendDisplayGuildBankSlot(WorldPacket& data, GuildBankTab const *ta } } -Item* Guild::StoreItem(uint8 tabId, GuildItemPosCountVec const& dest, Item* pItem) +Item* Guild::StoreItem(uint8 tabId, GuildItemPosCountVec const& dest, Item* pItem, SQLTransaction& trans) { if (!pItem) return NULL; @@ -1653,18 +1653,18 @@ Item* Guild::StoreItem(uint8 tabId, GuildItemPosCountVec const& dest, Item* pIte if (itr == dest.end()) { - lastItem = _StoreItem(tabId, slot, pItem, count, false); + lastItem = _StoreItem(tabId, slot, pItem, count, false, trans); break; } - lastItem = _StoreItem(tabId, slot, pItem, count, true); + lastItem = _StoreItem(tabId, slot, pItem, count, true, trans); } return lastItem; } // Return stored item (if stored to stack, it can diff. from pItem). And pItem ca be deleted in this case. -Item* Guild::_StoreItem(uint8 tab, uint8 slot, Item *pItem, uint32 count, bool clone) +Item* Guild::_StoreItem(uint8 tab, uint8 slot, Item *pItem, uint32 count, bool clone, SQLTransaction& trans) { if (!pItem) return NULL; @@ -1689,7 +1689,7 @@ Item* Guild::_StoreItem(uint8 tab, uint8 slot, Item *pItem, uint32 count, bool c pItem->SetUInt64Value(ITEM_FIELD_OWNER, 0); AddGBankItemToDB(GetId(), tab, slot, pItem->GetGUIDLow(), pItem->GetEntry()); pItem->FSetState(ITEM_NEW); - pItem->SaveToDB(); // not in inventory and can be save standalone + pItem->SaveToDB(trans); // not in inventory and can be save standalone return pItem; } @@ -1697,12 +1697,12 @@ Item* Guild::_StoreItem(uint8 tab, uint8 slot, Item *pItem, uint32 count, bool c { pItem2->SetCount(pItem2->GetCount() + count); pItem2->FSetState(ITEM_CHANGED); - pItem2->SaveToDB(); // not in inventory and can be save standalone + pItem2->SaveToDB(trans); // not in inventory and can be save standalone if (!clone) { pItem->RemoveFromWorld(); - pItem->DeleteFromDB(); + pItem->DeleteFromDB(trans); delete pItem; } @@ -1710,10 +1710,10 @@ Item* Guild::_StoreItem(uint8 tab, uint8 slot, Item *pItem, uint32 count, bool c } } -void Guild::RemoveItem(uint8 tab, uint8 slot) +void Guild::RemoveItem(uint8 tab, uint8 slot, SQLTransaction& trans) { m_TabListMap[tab]->Slots[slot] = NULL; - CharacterDatabase.PExecute("DELETE FROM guild_bank_item WHERE guildid='%u' AND TabId='%u' AND SlotId='%u'", + trans->PAppend("DELETE FROM guild_bank_item WHERE guildid='%u' AND TabId='%u' AND SlotId='%u'", GetId(), uint32(tab), uint32(slot)); } @@ -1954,15 +1954,15 @@ void Guild::SwapItems(Player * pl, uint8 BankTab, uint8 BankTabSlot, uint8 BankT return; } - CharacterDatabase.BeginTransaction(); - LogBankEvent(GUILD_BANK_LOG_MOVE_ITEM, BankTab, pl->GetGUIDLow(), pItemSrc->GetEntry(), SplitedAmount, BankTabDst); + SQLTransaction trans = CharacterDatabase.BeginTransaction(); + LogBankEvent(trans, GUILD_BANK_LOG_MOVE_ITEM, BankTab, pl->GetGUIDLow(), pItemSrc->GetEntry(), SplitedAmount, BankTabDst); pl->ItemRemovedQuestCheck(pItemSrc->GetEntry(), SplitedAmount); pItemSrc->SetCount(pItemSrc->GetCount() - SplitedAmount); pItemSrc->FSetState(ITEM_CHANGED); - pItemSrc->SaveToDB(); // not in inventory and can be save standalone - StoreItem(BankTabDst, dest, pNewItem); - CharacterDatabase.CommitTransaction(); + pItemSrc->SaveToDB(trans); // not in inventory and can be save standalone + StoreItem(BankTabDst, dest, pNewItem, trans); + CharacterDatabase.CommitTransaction(trans); } else // non split { @@ -1970,12 +1970,12 @@ void Guild::SwapItems(Player * pl, uint8 BankTab, uint8 BankTabSlot, uint8 BankT uint8 msg = CanStoreItem(BankTabDst, BankTabSlotDst, gDest, pItemSrc->GetCount(), pItemSrc, false); if (msg == EQUIP_ERR_OK) // merge to { - CharacterDatabase.BeginTransaction(); - LogBankEvent(GUILD_BANK_LOG_MOVE_ITEM, BankTab, pl->GetGUIDLow(), pItemSrc->GetEntry(), pItemSrc->GetCount(), BankTabDst); + SQLTransaction trans = CharacterDatabase.BeginTransaction(); + LogBankEvent(trans, GUILD_BANK_LOG_MOVE_ITEM, BankTab, pl->GetGUIDLow(), pItemSrc->GetEntry(), pItemSrc->GetCount(), BankTabDst); - RemoveItem(BankTab, BankTabSlot); - StoreItem(BankTabDst, gDest, pItemSrc); - CharacterDatabase.CommitTransaction(); + RemoveItem(BankTab, BankTabSlot, trans); + StoreItem(BankTabDst, gDest, pItemSrc, trans); + CharacterDatabase.CommitTransaction(trans); } else // swap { @@ -2007,15 +2007,15 @@ void Guild::SwapItems(Player * pl, uint8 BankTab, uint8 BankTabSlot, uint8 BankT return; } - CharacterDatabase.BeginTransaction(); - LogBankEvent(GUILD_BANK_LOG_MOVE_ITEM, BankTab, pl->GetGUIDLow(), pItemSrc->GetEntry(), pItemSrc->GetCount(), BankTabDst); - LogBankEvent(GUILD_BANK_LOG_MOVE_ITEM, BankTabDst, pl->GetGUIDLow(), pItemDst->GetEntry(), pItemDst->GetCount(), BankTab); + SQLTransaction trans = CharacterDatabase.BeginTransaction(); + LogBankEvent(trans, GUILD_BANK_LOG_MOVE_ITEM, BankTab, pl->GetGUIDLow(), pItemSrc->GetEntry(), pItemSrc->GetCount(), BankTabDst); + LogBankEvent(trans, GUILD_BANK_LOG_MOVE_ITEM, BankTabDst, pl->GetGUIDLow(), pItemDst->GetEntry(), pItemDst->GetCount(), BankTab); - RemoveItem(BankTab, BankTabSlot); - RemoveItem(BankTabDst, BankTabSlotDst); - StoreItem(BankTab, gSrc, pItemDst); - StoreItem(BankTabDst, gDest, pItemSrc); - CharacterDatabase.CommitTransaction(); + RemoveItem(BankTab, BankTabSlot, trans); + RemoveItem(BankTabDst, BankTabSlotDst, trans); + StoreItem(BankTab, gSrc, pItemDst, trans); + StoreItem(BankTabDst, gDest, pItemSrc, trans); + CharacterDatabase.CommitTransaction(trans); } } DisplayGuildBankContentUpdate(BankTab,BankTabSlot,BankTab == BankTabDst ? BankTabSlotDst : -1); @@ -2062,17 +2062,17 @@ void Guild::MoveFromBankToChar(Player * pl, uint8 BankTab, uint8 BankTabSlot, ui return; } - CharacterDatabase.BeginTransaction(); - LogBankEvent(GUILD_BANK_LOG_WITHDRAW_ITEM, BankTab, pl->GetGUIDLow(), pItemBank->GetEntry(), SplitedAmount); + SQLTransaction trans = CharacterDatabase.BeginTransaction(); + LogBankEvent(trans, GUILD_BANK_LOG_WITHDRAW_ITEM, BankTab, pl->GetGUIDLow(), pItemBank->GetEntry(), SplitedAmount); pItemBank->SetCount(pItemBank->GetCount()-SplitedAmount); pItemBank->FSetState(ITEM_CHANGED); - pItemBank->SaveToDB(); // not in inventory and can be save standalone + pItemBank->SaveToDB(trans); // not in inventory and can be save standalone pl->MoveItemToInventory(dest, pNewItem, true); - pl->SaveInventoryAndGoldToDB(); + pl->SaveInventoryAndGoldToDB(trans); - MemberItemWithdraw(BankTab, pl->GetGUIDLow()); - CharacterDatabase.CommitTransaction(); + MemberItemWithdraw(BankTab, pl->GetGUIDLow(), trans); + CharacterDatabase.CommitTransaction(trans); } else // Bank -> Char swap with slot (move) { @@ -2085,15 +2085,15 @@ void Guild::MoveFromBankToChar(Player * pl, uint8 BankTab, uint8 BankTabSlot, ui if (remRight <= 0) return; - CharacterDatabase.BeginTransaction(); - LogBankEvent(GUILD_BANK_LOG_WITHDRAW_ITEM, BankTab, pl->GetGUIDLow(), pItemBank->GetEntry(), pItemBank->GetCount()); + SQLTransaction trans = CharacterDatabase.BeginTransaction(); + LogBankEvent(trans, GUILD_BANK_LOG_WITHDRAW_ITEM, BankTab, pl->GetGUIDLow(), pItemBank->GetEntry(), pItemBank->GetCount()); - RemoveItem(BankTab, BankTabSlot); + RemoveItem(BankTab, BankTabSlot, trans); pl->MoveItemToInventory(dest, pItemBank, true); - pl->SaveInventoryAndGoldToDB(); + pl->SaveInventoryAndGoldToDB(trans); - MemberItemWithdraw(BankTab, pl->GetGUIDLow()); - CharacterDatabase.CommitTransaction(); + MemberItemWithdraw(BankTab, pl->GetGUIDLow(), trans); + CharacterDatabase.CommitTransaction(trans); } else // Bank <-> Char swap items { @@ -2146,25 +2146,25 @@ void Guild::MoveFromBankToChar(Player * pl, uint8 BankTab, uint8 BankTabSlot, ui } } - CharacterDatabase.BeginTransaction(); - LogBankEvent(GUILD_BANK_LOG_WITHDRAW_ITEM, BankTab, pl->GetGUIDLow(), pItemBank->GetEntry(), pItemBank->GetCount()); + SQLTransaction trans = CharacterDatabase.BeginTransaction(); + LogBankEvent(trans, GUILD_BANK_LOG_WITHDRAW_ITEM, BankTab, pl->GetGUIDLow(), pItemBank->GetEntry(), pItemBank->GetCount()); if (pItemChar) - LogBankEvent(GUILD_BANK_LOG_DEPOSIT_ITEM, BankTab, pl->GetGUIDLow(), pItemChar->GetEntry(), pItemChar->GetCount()); + LogBankEvent(trans, GUILD_BANK_LOG_DEPOSIT_ITEM, BankTab, pl->GetGUIDLow(), pItemChar->GetEntry(), pItemChar->GetCount()); - RemoveItem(BankTab, BankTabSlot); + RemoveItem(BankTab, BankTabSlot, trans); if (pItemChar) { pl->MoveItemFromInventory(PlayerBag, PlayerSlot, true); - pItemChar->DeleteFromInventoryDB(); + pItemChar->DeleteFromInventoryDB(trans); } if (pItemChar) - StoreItem(BankTab, gDest, pItemChar); + StoreItem(BankTab, gDest, pItemChar, trans); pl->MoveItemToInventory(iDest, pItemBank, true); - pl->SaveInventoryAndGoldToDB(); + pl->SaveInventoryAndGoldToDB(trans); - MemberItemWithdraw(BankTab, pl->GetGUIDLow()); - CharacterDatabase.CommitTransaction(); + MemberItemWithdraw(BankTab, pl->GetGUIDLow(), trans); + CharacterDatabase.CommitTransaction(trans); } } DisplayGuildBankContentUpdate(BankTab,BankTabSlot); @@ -2218,15 +2218,15 @@ void Guild::MoveFromCharToBank(Player * pl, uint8 PlayerBag, uint8 PlayerSlot, u pItemChar->GetProto()->Name1, pItemChar->GetEntry(), SplitedAmount,m_Id); } - CharacterDatabase.BeginTransaction(); - LogBankEvent(GUILD_BANK_LOG_DEPOSIT_ITEM, BankTab, pl->GetGUIDLow(), pItemChar->GetEntry(), SplitedAmount); + SQLTransaction trans = CharacterDatabase.BeginTransaction(); + LogBankEvent(trans, GUILD_BANK_LOG_DEPOSIT_ITEM, BankTab, pl->GetGUIDLow(), pItemChar->GetEntry(), SplitedAmount); pl->ItemRemovedQuestCheck(pItemChar->GetEntry(), SplitedAmount); pItemChar->SetCount(pItemChar->GetCount()-SplitedAmount); pItemChar->SetState(ITEM_CHANGED, pl); - pl->SaveInventoryAndGoldToDB(); - StoreItem(BankTab, dest, pNewItem); - CharacterDatabase.CommitTransaction(); + pl->SaveInventoryAndGoldToDB(trans); + StoreItem(BankTab, dest, pNewItem, trans); + CharacterDatabase.CommitTransaction(trans); DisplayGuildBankContentUpdate(BankTab, dest); } @@ -2245,15 +2245,15 @@ void Guild::MoveFromCharToBank(Player * pl, uint8 PlayerBag, uint8 PlayerSlot, u m_Id); } - CharacterDatabase.BeginTransaction(); - LogBankEvent(GUILD_BANK_LOG_DEPOSIT_ITEM, BankTab, pl->GetGUIDLow(), pItemChar->GetEntry(), pItemChar->GetCount()); + SQLTransaction trans = CharacterDatabase.BeginTransaction(); + LogBankEvent(trans, GUILD_BANK_LOG_DEPOSIT_ITEM, BankTab, pl->GetGUIDLow(), pItemChar->GetEntry(), pItemChar->GetCount()); pl->MoveItemFromInventory(PlayerBag, PlayerSlot, true); - pItemChar->DeleteFromInventoryDB(); + pItemChar->DeleteFromInventoryDB(trans); - StoreItem(BankTab, dest, pItemChar); - pl->SaveInventoryAndGoldToDB(); - CharacterDatabase.CommitTransaction(); + StoreItem(BankTab, dest, pItemChar, trans); + pl->SaveInventoryAndGoldToDB(trans); + CharacterDatabase.CommitTransaction(trans); DisplayGuildBankContentUpdate(BankTab, dest); } @@ -2295,23 +2295,23 @@ void Guild::MoveFromCharToBank(Player * pl, uint8 PlayerBag, uint8 PlayerSlot, u m_Id); } - CharacterDatabase.BeginTransaction(); + SQLTransaction trans = CharacterDatabase.BeginTransaction(); if (pItemBank) - LogBankEvent(GUILD_BANK_LOG_WITHDRAW_ITEM, BankTab, pl->GetGUIDLow(), pItemBank->GetEntry(), pItemBank->GetCount()); - LogBankEvent(GUILD_BANK_LOG_DEPOSIT_ITEM, BankTab, pl->GetGUIDLow(), pItemChar->GetEntry(), pItemChar->GetCount()); + LogBankEvent(trans, GUILD_BANK_LOG_WITHDRAW_ITEM, BankTab, pl->GetGUIDLow(), pItemBank->GetEntry(), pItemBank->GetCount()); + LogBankEvent(trans, GUILD_BANK_LOG_DEPOSIT_ITEM, BankTab, pl->GetGUIDLow(), pItemChar->GetEntry(), pItemChar->GetCount()); pl->MoveItemFromInventory(PlayerBag, PlayerSlot, true); - pItemChar->DeleteFromInventoryDB(); + pItemChar->DeleteFromInventoryDB(trans); if (pItemBank) - RemoveItem(BankTab, BankTabSlot); + RemoveItem(BankTab, BankTabSlot, trans); - StoreItem(BankTab,gDest,pItemChar); + StoreItem(BankTab,gDest,pItemChar, trans); if (pItemBank) pl->MoveItemToInventory(iDest, pItemBank, true); - pl->SaveInventoryAndGoldToDB(); + pl->SaveInventoryAndGoldToDB(trans); if (pItemBank) - MemberItemWithdraw(BankTab, pl->GetGUIDLow()); - CharacterDatabase.CommitTransaction(); + MemberItemWithdraw(BankTab, pl->GetGUIDLow(), trans); + CharacterDatabase.CommitTransaction(trans); DisplayGuildBankContentUpdate(BankTab, gDest); } @@ -2350,7 +2350,7 @@ void Guild::BroadcastEvent(GuildEvents event, uint64 guid, uint8 strCount, std:: sLog.outDebug("WORLD: Sent SMSG_GUILD_EVENT"); } -void Guild::DeleteGuildBankItems( bool alsoInDB /*= false*/ ) +void Guild::DeleteGuildBankItems( bool alsoInDB /*= false*/, SQLTransaction& trans) { for (size_t i = 0; i < m_TabListMap.size(); ++i) { @@ -2361,7 +2361,7 @@ void Guild::DeleteGuildBankItems( bool alsoInDB /*= false*/ ) pItem->RemoveFromWorld(); if (alsoInDB) - pItem->DeleteFromDB(); + pItem->DeleteFromDB(trans); delete pItem; } diff --git a/src/server/game/Guilds/Guild.h b/src/server/game/Guilds/Guild.h index 02840da82d3..fcf7429fbd1 100644 --- a/src/server/game/Guilds/Guild.h +++ b/src/server/game/Guilds/Guild.h @@ -294,7 +294,7 @@ class Guild void CreateDefaultGuildRanks(int locale_idx); void Disband(); - void DeleteGuildBankItems(bool alsoInDB = false); + void DeleteGuildBankItems(bool alsoInDB = false, SQLTransaction& trans = SQLTransaction(NULL)); typedef std::map<uint32, MemberSlot> MemberList; typedef std::vector<RankInfo> RankList; @@ -412,11 +412,11 @@ class Guild void LoadGuildBankFromDB(); // Money deposit/withdraw void SendMoneyInfo(WorldSession *session, uint32 LowGuid); - bool MemberMoneyWithdraw(uint32 amount, uint32 LowGuid); + bool MemberMoneyWithdraw(uint32 amount, uint32 LowGuid, SQLTransaction& trans); uint64 GetGuildBankMoney() { return m_GuildBankMoney; } - void SetBankMoney(int64 money); + void SetBankMoney(int64 money, SQLTransaction& trans); // per days - bool MemberItemWithdraw(uint8 TabId, uint32 LowGuid); + bool MemberItemWithdraw(uint8 TabId, uint32 LowGuid, SQLTransaction& trans); uint32 GetMemberSlotWithdrawRem(uint32 LowGuid, uint8 TabId); uint32 GetMemberMoneyWithdrawRem(uint32 LowGuid); void SetBankMoneyPerDay(uint32 rankId, uint32 money); @@ -428,7 +428,7 @@ class Guild // Guild Bank Event Logs void LoadGuildBankEventLogFromDB(); void DisplayGuildBankLogs(WorldSession *session, uint8 TabId); - void LogBankEvent(uint8 EventType, uint8 TabId, uint32 PlayerGuidLow, uint32 ItemOrMoney, uint8 ItemStackCount=0, uint8 DestTabId=0); + void LogBankEvent(SQLTransaction& trans, uint8 EventType, uint8 TabId, uint32 PlayerGuidLow, uint32 ItemOrMoney, uint8 ItemStackCount=0, uint8 DestTabId=0); bool AddGBankItemToDB(uint32 GuildId, uint32 BankTab , uint32 BankTabSlot , uint32 GUIDLow, uint32 Entry); protected: @@ -473,8 +473,8 @@ class Guild // used only from high level Swap/Move functions Item* GetItem(uint8 TabId, uint8 SlotId); uint8 CanStoreItem(uint8 tab, uint8 slot, GuildItemPosCountVec& dest, uint32 count, Item *pItem, bool swap = false) const; - Item* StoreItem(uint8 tab, GuildItemPosCountVec const& pos, Item *pItem); - void RemoveItem(uint8 tab, uint8 slot); + Item* StoreItem(uint8 tab, GuildItemPosCountVec const& pos, Item *pItem, SQLTransaction& trans); + void RemoveItem(uint8 tab, uint8 slot, SQLTransaction& trans); void DisplayGuildBankContentUpdate(uint8 TabId, int32 slot1, int32 slot2 = -1); void DisplayGuildBankContentUpdate(uint8 TabId, GuildItemPosCountVec const& slots); @@ -482,6 +482,6 @@ class Guild void AppendDisplayGuildBankSlot(WorldPacket& data, GuildBankTab const *tab, int32 slot); uint8 _CanStoreItem_InSpecificSlot(uint8 tab, uint8 slot, GuildItemPosCountVec& dest, uint32& count, bool swap, Item *pSrcItem) const; uint8 _CanStoreItem_InTab(uint8 tab, GuildItemPosCountVec& dest, uint32& count, bool merge, Item *pSrcItem, uint8 skip_slot) const; - Item* _StoreItem(uint8 tab, uint8 slot, Item *pItem, uint32 count, bool clone); + Item* _StoreItem(uint8 tab, uint8 slot, Item *pItem, uint32 count, bool clone, SQLTransaction& trans); }; #endif diff --git a/src/server/game/Instances/InstanceSaveMgr.cpp b/src/server/game/Instances/InstanceSaveMgr.cpp index 9e3e6eaa07f..54a713bf47e 100644 --- a/src/server/game/Instances/InstanceSaveMgr.cpp +++ b/src/server/game/Instances/InstanceSaveMgr.cpp @@ -124,11 +124,11 @@ InstanceSave *InstanceSaveManager::GetInstanceSave(uint32 InstanceId) void InstanceSaveManager::DeleteInstanceFromDB(uint32 instanceid) { - CharacterDatabase.BeginTransaction(); - CharacterDatabase.PExecute("DELETE FROM instance WHERE id = '%u'", instanceid); - CharacterDatabase.PExecute("DELETE FROM character_instance WHERE instance = '%u'", instanceid); - CharacterDatabase.PExecute("DELETE FROM group_instance WHERE instance = '%u'", instanceid); - CharacterDatabase.CommitTransaction(); + SQLTransaction trans = CharacterDatabase.BeginTransaction(); + trans->PAppend("DELETE FROM instance WHERE id = '%u'", instanceid); + trans->PAppend("DELETE FROM character_instance WHERE instance = '%u'", instanceid); + trans->PAppend("DELETE FROM group_instance WHERE instance = '%u'", instanceid); + CharacterDatabase.CommitTransaction(trans); // respawn times should be deleted only when the map gets unloaded } @@ -648,11 +648,11 @@ void InstanceSaveManager::_ResetOrWarnAll(uint32 mapid, Difficulty difficulty, b } // delete them from the DB, even if not loaded - CharacterDatabase.BeginTransaction(); - CharacterDatabase.PExecute("DELETE FROM character_instance USING character_instance LEFT JOIN instance ON character_instance.instance = id WHERE map = '%u' and difficulty='%u'", mapid, difficulty); - CharacterDatabase.PExecute("DELETE FROM group_instance USING group_instance LEFT JOIN instance ON group_instance.instance = id WHERE map = '%u' and difficulty='%u'", mapid, difficulty); - CharacterDatabase.PExecute("DELETE FROM instance WHERE map = '%u' and difficulty='%u'", mapid, difficulty); - CharacterDatabase.CommitTransaction(); + SQLTransaction trans = CharacterDatabase.BeginTransaction(); + trans->PAppend("DELETE FROM character_instance USING character_instance LEFT JOIN instance ON character_instance.instance = id WHERE map = '%u' and difficulty='%u'", mapid, difficulty); + trans->PAppend("DELETE FROM group_instance USING group_instance LEFT JOIN instance ON group_instance.instance = id WHERE map = '%u' and difficulty='%u'", mapid, difficulty); + trans->PAppend("DELETE FROM instance WHERE map = '%u' and difficulty='%u'", mapid, difficulty); + CharacterDatabase.CommitTransaction(trans); // calculate the next reset time uint32 diff = sWorld.getConfig(CONFIG_INSTANCE_RESET_TIME_HOUR) * HOUR; diff --git a/src/server/game/Mails/Mail.cpp b/src/server/game/Mails/Mail.cpp index beee96c0d91..00d82ca6860 100644 --- a/src/server/game/Mails/Mail.cpp +++ b/src/server/game/Mails/Mail.cpp @@ -245,6 +245,8 @@ void WorldSession::HandleSendMail(WorldPacket & recv_data) MailDraft draft(subject, body); + SQLTransaction trans = CharacterDatabase.BeginTransaction(); + if (items_count > 0 || money > 0) { if (items_count > 0) @@ -260,12 +262,11 @@ void WorldSession::HandleSendMail(WorldPacket & recv_data) item->SetNotRefundable(GetPlayer()); // makes the item no longer refundable pl->MoveItemFromInventory(items[i]->GetBagSlot(), item->GetSlot(), true); - CharacterDatabase.BeginTransaction(); - item->DeleteFromInventoryDB(); // deletes item from character's inventory - item->SaveToDB(); // recursive and not have transaction guard into self, item not in inventory and can be save standalone + + item->DeleteFromInventoryDB(trans); // deletes item from character's inventory + item->SaveToDB(trans); // recursive and not have transaction guard into self, item not in inventory and can be save standalone // owner in data will set at mail receive and item extracting - CharacterDatabase.PExecute("UPDATE item_instance SET owner_guid = '%u' WHERE guid='%u'", GUID_LOPART(rc), item->GetGUIDLow()); - CharacterDatabase.CommitTransaction(); + trans->PAppend("UPDATE item_instance SET owner_guid = '%u' WHERE guid='%u'", GUID_LOPART(rc), item->GetGUIDLow()); draft.AddItem(item); } @@ -287,11 +288,10 @@ void WorldSession::HandleSendMail(WorldPacket & recv_data) draft .AddMoney(money) .AddCOD(COD) - .SendMailTo(MailReceiver(receive, GUID_LOPART(rc)), pl, body.empty() ? MAIL_CHECK_MASK_COPIED : MAIL_CHECK_MASK_HAS_BODY, deliver_delay); + .SendMailTo(trans, MailReceiver(receive, GUID_LOPART(rc)), pl, body.empty() ? MAIL_CHECK_MASK_COPIED : MAIL_CHECK_MASK_HAS_BODY, deliver_delay); - CharacterDatabase.BeginTransaction(); - pl->SaveInventoryAndGoldToDB(); - CharacterDatabase.CommitTransaction(); + pl->SaveInventoryAndGoldToDB(trans); + CharacterDatabase.CommitTransaction(trans); } //called when mail is read @@ -366,10 +366,10 @@ void WorldSession::HandleMailReturnToSender(WorldPacket & recv_data) } //we can return mail now //so firstly delete the old one - CharacterDatabase.BeginTransaction(); - CharacterDatabase.PExecute("DELETE FROM mail WHERE id = '%u'", mailId); // needed? - CharacterDatabase.PExecute("DELETE FROM mail_items WHERE mail_id = '%u'", mailId); - CharacterDatabase.CommitTransaction(); + SQLTransaction trans = CharacterDatabase.BeginTransaction(); + trans->PAppend("DELETE FROM mail WHERE id = '%u'", mailId); // needed? + trans->PAppend("DELETE FROM mail_items WHERE mail_id = '%u'", mailId); + CharacterDatabase.CommitTransaction(trans); pl->RemoveMail(mailId); // only return mail if the player exists (and delete if not existing) @@ -436,6 +436,7 @@ void WorldSession::HandleMailTakeItem(WorldPacket & recv_data) uint8 msg = _player->CanStoreItem(NULL_BAG, NULL_SLOT, dest, it, false); if (msg == EQUIP_ERR_OK) { + SQLTransaction trans = CharacterDatabase.BeginTransaction(); m->RemoveItem(itemId); m->removedItems.push_back(itemId); @@ -473,7 +474,7 @@ void WorldSession::HandleMailTakeItem(WorldPacket & recv_data) { MailDraft(m->subject, "") .AddMoney(m->COD) - .SendMailTo(MailReceiver(receive, m->sender), MailSender(MAIL_NORMAL, m->receiver), MAIL_CHECK_MASK_COD_PAYMENT); + .SendMailTo(trans, MailReceiver(receive, m->sender), MailSender(MAIL_NORMAL, m->receiver), MAIL_CHECK_MASK_COD_PAYMENT); } pl->ModifyMoney(-int32(m->COD)); @@ -486,10 +487,9 @@ void WorldSession::HandleMailTakeItem(WorldPacket & recv_data) uint32 count = it->GetCount(); // save counts before store and possible merge with deleting pl->MoveItemToInventory(dest,it,true); - CharacterDatabase.BeginTransaction(); - pl->SaveInventoryAndGoldToDB(); - pl->_SaveMail(); - CharacterDatabase.CommitTransaction(); + pl->SaveInventoryAndGoldToDB(trans); + pl->_SaveMail(trans); + CharacterDatabase.CommitTransaction(trans); pl->SendMailResult(mailId, MAIL_ITEM_TAKEN, MAIL_OK, 0, itemId, count); } @@ -524,10 +524,10 @@ void WorldSession::HandleMailTakeMoney(WorldPacket & recv_data) pl->m_mailsUpdated = true; // save money and mail to prevent cheating - CharacterDatabase.BeginTransaction(); - pl->SaveGoldToDB(); - pl->_SaveMail(); - CharacterDatabase.CommitTransaction(); + SQLTransaction trans = CharacterDatabase.BeginTransaction(); + pl->SaveGoldToDB(trans); + pl->_SaveMail(trans); + CharacterDatabase.CommitTransaction(trans); } //called when player lists his received mails @@ -826,7 +826,7 @@ MailDraft& MailDraft::AddItem(Item* item) m_items[item->GetGUIDLow()] = item; return *this; } -void MailDraft::prepareItems(Player* receiver) +void MailDraft::prepareItems(Player* receiver, SQLTransaction& trans) { if (!m_mailTemplateId || !m_mailTemplateItemsNeed) return; @@ -845,21 +845,21 @@ void MailDraft::prepareItems(Player* receiver) { if (Item* item = Item::CreateItem(lootitem->itemid,lootitem->count,receiver)) { - item->SaveToDB(); // save for prevent lost at next mail load, if send fail then item will deleted + item->SaveToDB(trans); // save for prevent lost at next mail load, if send fail then item will deleted AddItem(item); } } } } -void MailDraft::deleteIncludedItems(bool inDB /*= false*/) +void MailDraft::deleteIncludedItems(bool inDB /*= false*/, SQLTransaction& trans) { for (MailItemMap::iterator mailItemIter = m_items.begin(); mailItemIter != m_items.end(); ++mailItemIter) { Item* item = mailItemIter->second; if (inDB) - CharacterDatabase.PExecute("DELETE FROM item_instance WHERE guid='%u'", item->GetGUIDLow()); + trans->PAppend("DELETE FROM item_instance WHERE guid='%u'", item->GetGUIDLow()); delete item; } @@ -875,9 +875,11 @@ void MailDraft::SendReturnToSender(uint32 sender_acc, uint32 sender_guid, uint32 if (!receiver) rc_account = sObjectMgr.GetPlayerAccountIdByGUID(MAKE_NEW_GUID(receiver_guid, 0, HIGHGUID_PLAYER)); + SQLTransaction trans = CharacterDatabase.BeginTransaction(); + if (!receiver && !rc_account) // sender not exist { - deleteIncludedItems(true); + deleteIncludedItems(true, trans); return; } @@ -890,30 +892,29 @@ void MailDraft::SendReturnToSender(uint32 sender_acc, uint32 sender_guid, uint32 needItemDelay = sender_acc != rc_account; // set owner to new receiver (to prevent delete item with sender char deleting) - CharacterDatabase.BeginTransaction(); for (MailItemMap::iterator mailItemIter = m_items.begin(); mailItemIter != m_items.end(); ++mailItemIter) { Item* item = mailItemIter->second; - item->SaveToDB(); // item not in inventory and can be save standalone + item->SaveToDB(trans); // item not in inventory and can be save standalone // owner in data will set at mail receive and item extracting - CharacterDatabase.PExecute("UPDATE item_instance SET owner_guid = '%u' WHERE guid='%u'", receiver_guid, item->GetGUIDLow()); + trans->PAppend("UPDATE item_instance SET owner_guid = '%u' WHERE guid='%u'", receiver_guid, item->GetGUIDLow()); } - CharacterDatabase.CommitTransaction(); } // If theres is an item, there is a one hour delivery delay. uint32 deliver_delay = needItemDelay ? sWorld.getConfig(CONFIG_MAIL_DELIVERY_DELAY) : 0; // will delete item or place to receiver mail list - SendMailTo(MailReceiver(receiver,receiver_guid), MailSender(MAIL_NORMAL, sender_guid), MAIL_CHECK_MASK_RETURNED, deliver_delay); + SendMailTo(trans,MailReceiver(receiver,receiver_guid), MailSender(MAIL_NORMAL, sender_guid), MAIL_CHECK_MASK_RETURNED, deliver_delay); + CharacterDatabase.CommitTransaction(trans); } -void MailDraft::SendMailTo(MailReceiver const& receiver, MailSender const& sender, MailCheckMask checked, uint32 deliver_delay) +void MailDraft::SendMailTo(SQLTransaction& trans, MailReceiver const& receiver, MailSender const& sender, MailCheckMask checked, uint32 deliver_delay) { Player* pReceiver = receiver.GetPlayer(); // can be NULL if (pReceiver) - prepareItems(pReceiver); // generate mail template items + prepareItems(pReceiver, trans); // generate mail template items uint32 mailId = sObjectMgr.GenerateMailID(); @@ -937,20 +938,19 @@ void MailDraft::SendMailTo(MailReceiver const& receiver, MailSender const& sende // Add to DB std::string safe_subject = GetSubject(); std::string safe_body = GetBody(); - CharacterDatabase.BeginTransaction(); + CharacterDatabase.escape_string(safe_subject); CharacterDatabase.escape_string(safe_body); - CharacterDatabase.PExecute("INSERT INTO mail (id,messageType,stationery,mailTemplateId,sender,receiver,subject,body,has_items,expire_time,deliver_time,money,cod,checked) " + trans->PAppend("INSERT INTO mail (id,messageType,stationery,mailTemplateId,sender,receiver,subject,body,has_items,expire_time,deliver_time,money,cod,checked) " "VALUES ('%u', '%u', '%u', '%u', '%u', '%u', '%s', '%s', '%u', '" UI64FMTD "','" UI64FMTD "', '%u', '%u', '%d')", mailId, sender.GetMailMessageType(), sender.GetStationery(), GetMailTemplateId(), sender.GetSenderId(), receiver.GetPlayerGUIDLow(), safe_subject.c_str(), safe_body.c_str(),(m_items.empty() ? 0 : 1), (uint64)expire_time, (uint64)deliver_time, m_money, m_COD, checked); for (MailItemMap::const_iterator mailItemIter = m_items.begin(); mailItemIter != m_items.end(); ++mailItemIter) { Item* item = mailItemIter->second; - CharacterDatabase.PExecute("INSERT INTO mail_items (mail_id,item_guid,item_template,receiver) VALUES ('%u', '%u', '%u','%u')", mailId, item->GetGUIDLow(), item->GetEntry(), receiver.GetPlayerGUIDLow()); + trans->PAppend("INSERT INTO mail_items (mail_id,item_guid,item_template,receiver) VALUES ('%u', '%u', '%u','%u')", mailId, item->GetGUIDLow(), item->GetEntry(), receiver.GetPlayerGUIDLow()); } - CharacterDatabase.CommitTransaction(); // For online receiver update in game mail status and data if (pReceiver) diff --git a/src/server/game/Mails/Mail.h b/src/server/game/Mails/Mail.h index b0103897864..83a346d31c1 100644 --- a/src/server/game/Mails/Mail.h +++ b/src/server/game/Mails/Mail.h @@ -128,16 +128,19 @@ class MailDraft uint32 GetMoney() const { return m_money; } uint32 GetCOD() const { return m_COD; } std::string const& GetBody() const { return m_body; } + public: // modifiers MailDraft& AddItem(Item* item); MailDraft& AddMoney(uint32 money) { m_money = money; return *this; } MailDraft& AddCOD(uint32 COD) { m_COD = COD; return *this; } + public: // finishers void SendReturnToSender(uint32 sender_acc, uint32 sender_guid, uint32 receiver_guid); - void SendMailTo(MailReceiver const& receiver, MailSender const& sender, MailCheckMask checked = MAIL_CHECK_MASK_NONE, uint32 deliver_delay = 0); + void SendMailTo(SQLTransaction& trans, MailReceiver const& receiver, MailSender const& sender, MailCheckMask checked = MAIL_CHECK_MASK_NONE, uint32 deliver_delay = 0); + private: - void deleteIncludedItems(bool inDB = false); - void prepareItems(Player* receiver); // called from SendMailTo for generate mailTemplateBase items + void deleteIncludedItems(bool inDB = false, SQLTransaction& trans = SQLTransaction(NULL)); + void prepareItems(Player* receiver, SQLTransaction& trans); // called from SendMailTo for generate mailTemplateBase items uint16 m_mailTemplateId; bool m_mailTemplateItemsNeed; diff --git a/src/server/game/Reputation/ReputationMgr.cpp b/src/server/game/Reputation/ReputationMgr.cpp index 224092097ce..adf6c9a7433 100644 --- a/src/server/game/Reputation/ReputationMgr.cpp +++ b/src/server/game/Reputation/ReputationMgr.cpp @@ -508,14 +508,14 @@ void ReputationMgr::LoadFromDB(QueryResult_AutoPtr result) } } -void ReputationMgr::SaveToDB() +void ReputationMgr::SaveToDB(SQLTransaction& trans) { for (FactionStateList::iterator itr = m_factions.begin(); itr != m_factions.end(); ++itr) { if (itr->second.Changed) { - CharacterDatabase.PExecute("DELETE FROM character_reputation WHERE guid = '%u' AND faction='%u'", m_player->GetGUIDLow(), itr->second.ID); - CharacterDatabase.PExecute("INSERT INTO character_reputation (guid,faction,standing,flags) VALUES ('%u', '%u', '%i', '%u')", m_player->GetGUIDLow(), itr->second.ID, itr->second.Standing, itr->second.Flags); + trans->PAppend("DELETE FROM character_reputation WHERE guid = '%u' AND faction='%u'", m_player->GetGUIDLow(), itr->second.ID); + trans->PAppend("INSERT INTO character_reputation (guid,faction,standing,flags) VALUES ('%u', '%u', '%i', '%u')", m_player->GetGUIDLow(), itr->second.ID, itr->second.Standing, itr->second.Flags); itr->second.Changed = false; } } diff --git a/src/server/game/Reputation/ReputationMgr.h b/src/server/game/Reputation/ReputationMgr.h index 4c0fd778a4d..b3a01ffc86d 100644 --- a/src/server/game/Reputation/ReputationMgr.h +++ b/src/server/game/Reputation/ReputationMgr.h @@ -68,7 +68,7 @@ class ReputationMgr m_visibleFactionCount(0), m_honoredFactionCount(0), m_reveredFactionCount(0), m_exaltedFactionCount(0) {} ~ReputationMgr() {} - void SaveToDB(); + void SaveToDB(SQLTransaction& trans); void LoadFromDB(QueryResult_AutoPtr result); public: // statics static const int32 PointsInRank[MAX_REPUTATION_RANK]; diff --git a/src/server/game/Server/Protocol/Handlers/AuctionHouseHandler.cpp b/src/server/game/Server/Protocol/Handlers/AuctionHouseHandler.cpp index 3bd6cad64c6..3f399db9ac1 100644 --- a/src/server/game/Server/Protocol/Handlers/AuctionHouseHandler.cpp +++ b/src/server/game/Server/Protocol/Handlers/AuctionHouseHandler.cpp @@ -113,53 +113,6 @@ void WorldSession::SendAuctionOwnerNotification(AuctionEntry* auction) SendPacket(&data); } -//this function sends mail to old bidder -void WorldSession::SendAuctionOutbiddedMail(AuctionEntry *auction, uint32 newPrice) -{ - uint64 oldBidder_guid = MAKE_NEW_GUID(auction->bidder,0, HIGHGUID_PLAYER); - Player *oldBidder = sObjectMgr.GetPlayer(oldBidder_guid); - - uint32 oldBidder_accId = 0; - if (!oldBidder) - oldBidder_accId = sObjectMgr.GetPlayerAccountIdByGUID(oldBidder_guid); - - // old bidder exist - if (oldBidder || oldBidder_accId) - { - std::ostringstream msgAuctionOutbiddedSubject; - msgAuctionOutbiddedSubject << auction->item_template << ":0:" << AUCTION_OUTBIDDED << ":0:0"; - - if (oldBidder && _player) - oldBidder->GetSession()->SendAuctionBidderNotification(auction->GetHouseId(), auction->Id, _player->GetGUID(), newPrice, auction->GetAuctionOutBid(), auction->item_template); - - MailDraft(msgAuctionOutbiddedSubject.str(), "") // TODO: fix body - .AddMoney(auction->bid) - .SendMailTo(MailReceiver(oldBidder, auction->bidder), auction, MAIL_CHECK_MASK_COPIED); - } -} - -//this function sends mail, when auction is cancelled to old bidder -void WorldSession::SendAuctionCancelledToBidderMail(AuctionEntry* auction) -{ - uint64 bidder_guid = MAKE_NEW_GUID(auction->bidder, 0, HIGHGUID_PLAYER); - Player *bidder = sObjectMgr.GetPlayer(bidder_guid); - - uint32 bidder_accId = 0; - if (!bidder) - bidder_accId = sObjectMgr.GetPlayerAccountIdByGUID(bidder_guid); - - // bidder exist - if (bidder || bidder_accId) - { - std::ostringstream msgAuctionCancelledSubject; - msgAuctionCancelledSubject << auction->item_template << ":0:" << AUCTION_CANCELLED_TO_BIDDER << ":0:0"; - - MailDraft(msgAuctionCancelledSubject.str(), "") // TODO: fix body - .AddMoney(auction->bid) - .SendMailTo(MailReceiver(bidder, auction->bidder), auction, MAIL_CHECK_MASK_COPIED); - } -} - //this void creates new auction and adds auction to some auctionhouse void WorldSession::HandleAuctionSellItem(WorldPacket & recv_data) { @@ -284,12 +237,12 @@ void WorldSession::HandleAuctionSellItem(WorldPacket & recv_data) pl->MoveItemFromInventory(it->GetBagSlot(), it->GetSlot(), true); - CharacterDatabase.BeginTransaction(); - it->DeleteFromInventoryDB(); - it->SaveToDB(); // recursive and not have transaction guard into self, not in inventiory and can be save standalone - AH->SaveToDB(); - pl->SaveInventoryAndGoldToDB(); - CharacterDatabase.CommitTransaction(); + SQLTransaction trans = CharacterDatabase.BeginTransaction(); + it->DeleteFromInventoryDB(trans); + it->SaveToDB(trans); // recursive and not have transaction guard into self, not in inventiory and can be save standalone + AH->SaveToDB(trans); + pl->SaveInventoryAndGoldToDB(trans); + CharacterDatabase.CommitTransaction(trans); SendAuctionCommandResult(AH->Id, AUCTION_SELL_ITEM, AUCTION_OK); @@ -359,6 +312,8 @@ void WorldSession::HandleAuctionPlaceBid(WorldPacket & recv_data) return; } + SQLTransaction trans = CharacterDatabase.BeginTransaction(); + if (price < auction->buyout || auction->buyout == 0) { if (auction->bidder > 0) @@ -368,7 +323,7 @@ void WorldSession::HandleAuctionPlaceBid(WorldPacket & recv_data) else { // mail to last bidder and return money - SendAuctionOutbiddedMail(auction, price); + sAuctionMgr.SendAuctionOutbiddedMail(auction, price, GetPlayer(), trans); pl->ModifyMoney(-int32(price)); } } @@ -379,9 +334,7 @@ void WorldSession::HandleAuctionPlaceBid(WorldPacket & recv_data) auction->bid = price; GetPlayer()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_BID, price); - // after this update we should save player's money ... - CharacterDatabase.BeginTransaction(); - CharacterDatabase.PExecute("UPDATE auctionhouse SET buyguid = '%u',lastbid = '%u' WHERE id = '%u'", auction->bidder, auction->bid, auction->Id); + trans->PAppend("UPDATE auctionhouse SET buyguid = '%u',lastbid = '%u' WHERE id = '%u'", auction->bidder, auction->bid, auction->Id); SendAuctionCommandResult(auction->Id, AUCTION_PLACE_BID, AUCTION_OK, 0); } @@ -394,26 +347,27 @@ void WorldSession::HandleAuctionPlaceBid(WorldPacket & recv_data) { pl->ModifyMoney(-int32(auction->buyout)); if (auction->bidder) //buyout for bidded auction .. - SendAuctionOutbiddedMail(auction, auction->buyout); + sAuctionMgr.SendAuctionOutbiddedMail(auction, auction->buyout, GetPlayer(), trans); } auction->bidder = pl->GetGUIDLow(); auction->bid = auction->buyout; GetPlayer()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_BID, auction->buyout); - sAuctionMgr.SendAuctionSalePendingMail(auction); - sAuctionMgr.SendAuctionSuccessfulMail(auction); - sAuctionMgr.SendAuctionWonMail(auction); + //- Mails must be under transaction control too to prevent data loss + sAuctionMgr.SendAuctionSalePendingMail(auction, trans); + sAuctionMgr.SendAuctionSuccessfulMail(auction, trans); + sAuctionMgr.SendAuctionWonMail(auction, trans); SendAuctionCommandResult(auction->Id, AUCTION_PLACE_BID, AUCTION_OK); - CharacterDatabase.BeginTransaction(); - auction->DeleteFromDB(); + auction->DeleteFromDB(trans); + uint32 item_template = auction->item_template; sAuctionMgr.RemoveAItem(auction->item_guidlow); auctionHouse->RemoveAuction(auction, item_template); } - pl->SaveInventoryAndGoldToDB(); - CharacterDatabase.CommitTransaction(); + pl->SaveInventoryAndGoldToDB(trans); + CharacterDatabase.CommitTransaction(trans); } //this void is called when auction_owner cancels his auction @@ -441,6 +395,7 @@ void WorldSession::HandleAuctionRemoveItem(WorldPacket & recv_data) AuctionEntry *auction = auctionHouse->GetAuction(auctionId); Player *pl = GetPlayer(); + SQLTransaction trans = CharacterDatabase.BeginTransaction(); if (auction && auction->owner == pl->GetGUIDLow()) { Item *pItem = sAuctionMgr.GetAItem(auction->item_guidlow); @@ -452,7 +407,7 @@ void WorldSession::HandleAuctionRemoveItem(WorldPacket & recv_data) if (pl->GetMoney() < auctionCut) //player doesn't have enough money, maybe message needed return; //some auctionBidderNotification would be needed, but don't know that parts.. - SendAuctionCancelledToBidderMail(auction); + sAuctionMgr.SendAuctionCancelledToBidderMail(auction, trans); pl->ModifyMoney(-int32(auctionCut)); } // Return the item by mail @@ -462,7 +417,7 @@ void WorldSession::HandleAuctionRemoveItem(WorldPacket & recv_data) // item will deleted or added to received mail list MailDraft(msgAuctionCanceledOwner.str(), "") // TODO: fix body .AddItem(pItem) - .SendMailTo(pl, auction, MAIL_CHECK_MASK_COPIED); + .SendMailTo(trans, pl, auction, MAIL_CHECK_MASK_COPIED); } else { @@ -483,13 +438,14 @@ void WorldSession::HandleAuctionRemoveItem(WorldPacket & recv_data) SendAuctionCommandResult(auction->Id, AUCTION_CANCEL, AUCTION_OK); // Now remove the auction - CharacterDatabase.BeginTransaction(); - pl->SaveInventoryAndGoldToDB(); - auction->DeleteFromDB(); + + pl->SaveInventoryAndGoldToDB(trans); + auction->DeleteFromDB(trans); + CharacterDatabase.CommitTransaction(trans); + uint32 item_template = auction->item_template; sAuctionMgr.RemoveAItem(auction->item_guidlow); auctionHouse->RemoveAuction(auction, item_template); - CharacterDatabase.CommitTransaction(); } //called when player lists his bids diff --git a/src/server/game/Server/Protocol/Handlers/CharacterHandler.cpp b/src/server/game/Server/Protocol/Handlers/CharacterHandler.cpp index 01c1392f35b..e6aec50179d 100644 --- a/src/server/game/Server/Protocol/Handlers/CharacterHandler.cpp +++ b/src/server/game/Server/Protocol/Handlers/CharacterHandler.cpp @@ -1041,11 +1041,11 @@ void WorldSession::HandleSetPlayerDeclinedNames(WorldPacket& recv_data) for (int i = 0; i < MAX_DECLINED_NAME_CASES; ++i) CharacterDatabase.escape_string(declinedname.name[i]); - CharacterDatabase.BeginTransaction(); - CharacterDatabase.PExecute("DELETE FROM character_declinedname WHERE guid = '%u'", GUID_LOPART(guid)); - CharacterDatabase.PExecute("INSERT INTO character_declinedname (guid, genitive, dative, accusative, instrumental, prepositional) VALUES ('%u','%s','%s','%s','%s','%s')", + SQLTransaction trans = CharacterDatabase.BeginTransaction(); + trans->PAppend("DELETE FROM character_declinedname WHERE guid = '%u'", GUID_LOPART(guid)); + trans->PAppend("INSERT INTO character_declinedname (guid, genitive, dative, accusative, instrumental, prepositional) VALUES ('%u','%s','%s','%s','%s','%s')", GUID_LOPART(guid), declinedname.name[0].c_str(), declinedname.name[1].c_str(), declinedname.name[2].c_str(), declinedname.name[3].c_str(), declinedname.name[4].c_str()); - CharacterDatabase.CommitTransaction(); + CharacterDatabase.CommitTransaction(trans); WorldPacket data(SMSG_SET_PLAYER_DECLINED_NAMES_RESULT, 4+8); data << uint32(0); // OK diff --git a/src/server/game/Server/Protocol/Handlers/GuildHandler.cpp b/src/server/game/Server/Protocol/Handlers/GuildHandler.cpp index d20284ae8f4..15bead6860d 100644 --- a/src/server/game/Server/Protocol/Handlers/GuildHandler.cpp +++ b/src/server/game/Server/Protocol/Handlers/GuildHandler.cpp @@ -887,13 +887,11 @@ void WorldSession::HandleGuildBankDepositMoney(WorldPacket & recv_data) if (!pGuild->GetPurchasedTabs()) return; - CharacterDatabase.BeginTransaction(); + SQLTransaction trans = CharacterDatabase.BeginTransaction(); - pGuild->SetBankMoney(pGuild->GetGuildBankMoney()+money); + pGuild->SetBankMoney(pGuild->GetGuildBankMoney()+money, trans); GetPlayer()->ModifyMoney(-int(money)); - GetPlayer()->SaveGoldToDB(); - - CharacterDatabase.CommitTransaction(); + GetPlayer()->SaveGoldToDB(trans); // logging money if (_player->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE)) @@ -903,7 +901,9 @@ void WorldSession::HandleGuildBankDepositMoney(WorldPacket & recv_data) } // log - pGuild->LogBankEvent(GUILD_BANK_LOG_DEPOSIT_MONEY, uint8(0), GetPlayer()->GetGUIDLow(), money); + pGuild->LogBankEvent(trans, GUILD_BANK_LOG_DEPOSIT_MONEY, uint8(0), GetPlayer()->GetGUIDLow(), money); + + CharacterDatabase.CommitTransaction(trans); pGuild->DisplayGuildBankTabsInfo(this); pGuild->DisplayGuildBankContent(this, 0); @@ -941,21 +941,18 @@ void WorldSession::HandleGuildBankWithdrawMoney(WorldPacket & recv_data) if (!pGuild->HasRankRight(GetPlayer()->GetRank(), GR_RIGHT_WITHDRAW_GOLD)) return; - CharacterDatabase.BeginTransaction(); + SQLTransaction trans = CharacterDatabase.BeginTransaction(); - if (!pGuild->MemberMoneyWithdraw(money, GetPlayer()->GetGUIDLow())) - { - CharacterDatabase.RollbackTransaction(); + if (!pGuild->MemberMoneyWithdraw(money, GetPlayer()->GetGUIDLow(), trans)) return; - } GetPlayer()->ModifyMoney(money); - GetPlayer()->SaveGoldToDB(); - - CharacterDatabase.CommitTransaction(); + GetPlayer()->SaveGoldToDB(trans); // Log - pGuild->LogBankEvent(GUILD_BANK_LOG_WITHDRAW_MONEY, uint8(0), GetPlayer()->GetGUIDLow(), money); + pGuild->LogBankEvent(trans, GUILD_BANK_LOG_WITHDRAW_MONEY, uint8(0), GetPlayer()->GetGUIDLow(), money); + + CharacterDatabase.CommitTransaction(trans); pGuild->SendMoneyInfo(this, GetPlayer()->GetGUIDLow()); pGuild->DisplayGuildBankTabsInfo(this); diff --git a/src/server/game/Server/Protocol/Handlers/ItemHandler.cpp b/src/server/game/Server/Protocol/Handlers/ItemHandler.cpp index 86c81172a61..cc973b25fbd 100644 --- a/src/server/game/Server/Protocol/Handlers/ItemHandler.cpp +++ b/src/server/game/Server/Protocol/Handlers/ItemHandler.cpp @@ -1120,8 +1120,8 @@ void WorldSession::HandleWrapItemOpcode(WorldPacket& recv_data) return; } - CharacterDatabase.BeginTransaction(); - CharacterDatabase.PExecute("INSERT INTO character_gifts VALUES ('%u', '%u', '%u', '%u')", GUID_LOPART(item->GetOwnerGUID()), item->GetGUIDLow(), item->GetEntry(), item->GetUInt32Value(ITEM_FIELD_FLAGS)); + SQLTransaction trans = CharacterDatabase.BeginTransaction(); + trans->PAppend("INSERT INTO character_gifts VALUES ('%u', '%u', '%u', '%u')", GUID_LOPART(item->GetOwnerGUID()), item->GetGUIDLow(), item->GetEntry(), item->GetUInt32Value(ITEM_FIELD_FLAGS)); item->SetEntry(gift->GetEntry()); switch (item->GetEntry()) @@ -1141,9 +1141,9 @@ void WorldSession::HandleWrapItemOpcode(WorldPacket& recv_data) { // after save it will be impossible to remove the item from the queue item->RemoveFromUpdateQueueOf(_player); - item->SaveToDB(); // item gave inventory record unchanged and can be save standalone + item->SaveToDB(trans); // item gave inventory record unchanged and can be save standalone } - CharacterDatabase.CommitTransaction(); + CharacterDatabase.CommitTransaction(trans); uint32 count = 1; _player->DestroyItemCount(gift, count, true); diff --git a/src/server/game/Server/Protocol/Handlers/NPCHandler.cpp b/src/server/game/Server/Protocol/Handlers/NPCHandler.cpp index 6e36c963277..37f2f4b4b62 100644 --- a/src/server/game/Server/Protocol/Handlers/NPCHandler.cpp +++ b/src/server/game/Server/Protocol/Handlers/NPCHandler.cpp @@ -863,7 +863,12 @@ void WorldSession::HandleRepairItemOpcode(WorldPacket & recv_data) Guild *pGuild = sObjectMgr.GetGuildById(GuildId); if (!pGuild) return; - pGuild->LogBankEvent(GUILD_BANK_LOG_REPAIR_MONEY, 0, _player->GetGUIDLow(), TotalCost); + + //- TODO: Fix poor function call design + SQLTransaction trans = CharacterDatabase.BeginTransaction(); + pGuild->LogBankEvent(trans, GUILD_BANK_LOG_REPAIR_MONEY, 0, _player->GetGUIDLow(), TotalCost); + CharacterDatabase.CommitTransaction(trans); + pGuild->SendMoneyInfo(this, _player->GetGUIDLow()); } } diff --git a/src/server/game/Server/Protocol/Handlers/PetHandler.cpp b/src/server/game/Server/Protocol/Handlers/PetHandler.cpp index 71454ce428f..8b0c496a89d 100644 --- a/src/server/game/Server/Protocol/Handlers/PetHandler.cpp +++ b/src/server/game/Server/Protocol/Handlers/PetHandler.cpp @@ -601,19 +601,19 @@ void WorldSession::HandlePetRename(WorldPacket & recv_data) } } - CharacterDatabase.BeginTransaction(); + SQLTransaction trans = CharacterDatabase.BeginTransaction(); if (isdeclined) { for (uint8 i = 0; i < MAX_DECLINED_NAME_CASES; ++i) CharacterDatabase.escape_string(declinedname.name[i]); - CharacterDatabase.PExecute("DELETE FROM character_pet_declinedname WHERE owner = '%u' AND id = '%u'", _player->GetGUIDLow(), pet->GetCharmInfo()->GetPetNumber()); - CharacterDatabase.PExecute("INSERT INTO character_pet_declinedname (id, owner, genitive, dative, accusative, instrumental, prepositional) VALUES ('%u','%u','%s','%s','%s','%s','%s')", + trans->PAppend("DELETE FROM character_pet_declinedname WHERE owner = '%u' AND id = '%u'", _player->GetGUIDLow(), pet->GetCharmInfo()->GetPetNumber()); + trans->PAppend("INSERT INTO character_pet_declinedname (id, owner, genitive, dative, accusative, instrumental, prepositional) VALUES ('%u','%u','%s','%s','%s','%s','%s')", pet->GetCharmInfo()->GetPetNumber(), _player->GetGUIDLow(), declinedname.name[0].c_str(), declinedname.name[1].c_str(), declinedname.name[2].c_str(), declinedname.name[3].c_str(), declinedname.name[4].c_str()); } CharacterDatabase.escape_string(name); - CharacterDatabase.PExecute("UPDATE character_pet SET name = '%s', renamed = '1' WHERE owner = '%u' AND id = '%u'", name.c_str(), _player->GetGUIDLow(), pet->GetCharmInfo()->GetPetNumber()); - CharacterDatabase.CommitTransaction(); + trans->PAppend("UPDATE character_pet SET name = '%s', renamed = '1' WHERE owner = '%u' AND id = '%u'", name.c_str(), _player->GetGUIDLow(), pet->GetCharmInfo()->GetPetNumber()); + CharacterDatabase.CommitTransaction(trans); pet->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, time(NULL)); } diff --git a/src/server/game/Server/Protocol/Handlers/PetitionsHandler.cpp b/src/server/game/Server/Protocol/Handlers/PetitionsHandler.cpp index 5248fb93289..6e9bf7e742b 100644 --- a/src/server/game/Server/Protocol/Handlers/PetitionsHandler.cpp +++ b/src/server/game/Server/Protocol/Handlers/PetitionsHandler.cpp @@ -225,12 +225,12 @@ void WorldSession::HandlePetitionBuyOpcode(WorldPacket & recv_data) sLog.outDebug("Invalid petition GUIDs: %s", ssInvalidPetitionGUIDs.str().c_str()); CharacterDatabase.escape_string(name); - CharacterDatabase.BeginTransaction(); - CharacterDatabase.PExecute("DELETE FROM petition WHERE petitionguid IN (%s)", ssInvalidPetitionGUIDs.str().c_str()); - CharacterDatabase.PExecute("DELETE FROM petition_sign WHERE petitionguid IN (%s)", ssInvalidPetitionGUIDs.str().c_str()); - CharacterDatabase.PExecute("INSERT INTO petition (ownerguid, petitionguid, name, type) VALUES ('%u', '%u', '%s', '%u')", + SQLTransaction trans = CharacterDatabase.BeginTransaction(); + trans->PAppend("DELETE FROM petition WHERE petitionguid IN (%s)", ssInvalidPetitionGUIDs.str().c_str()); + trans->PAppend("DELETE FROM petition_sign WHERE petitionguid IN (%s)", ssInvalidPetitionGUIDs.str().c_str()); + trans->PAppend("INSERT INTO petition (ownerguid, petitionguid, name, type) VALUES ('%u', '%u', '%s', '%u')", _player->GetGUIDLow(), charter->GetGUIDLow(), name.c_str(), type); - CharacterDatabase.CommitTransaction(); + CharacterDatabase.CommitTransaction(trans); } void WorldSession::HandlePetitionShowSignOpcode(WorldPacket & recv_data) @@ -845,10 +845,10 @@ void WorldSession::HandleTurnInPetitionOpcode(WorldPacket & recv_data) } } - CharacterDatabase.BeginTransaction(); - CharacterDatabase.PExecute("DELETE FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid)); - CharacterDatabase.PExecute("DELETE FROM petition_sign WHERE petitionguid = '%u'", GUID_LOPART(petitionguid)); - CharacterDatabase.CommitTransaction(); + SQLTransaction trans = CharacterDatabase.BeginTransaction(); + trans->PAppend("DELETE FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid)); + trans->PAppend("DELETE FROM petition_sign WHERE petitionguid = '%u'", GUID_LOPART(petitionguid)); + CharacterDatabase.CommitTransaction(trans); // created sLog.outDebug("TURN IN PETITION GUID %u", GUID_LOPART(petitionguid)); diff --git a/src/server/game/Server/Protocol/Handlers/TradeHandler.cpp b/src/server/game/Server/Protocol/Handlers/TradeHandler.cpp index 33bc48ace50..9a31c3b415c 100644 --- a/src/server/game/Server/Protocol/Handlers/TradeHandler.cpp +++ b/src/server/game/Server/Protocol/Handlers/TradeHandler.cpp @@ -480,10 +480,10 @@ void WorldSession::HandleAcceptTradeOpcode(WorldPacket& /*recvPacket*/) trader->m_trade = NULL; // desynchronized with the other saves here (SaveInventoryAndGoldToDB() not have own transaction guards) - CharacterDatabase.BeginTransaction(); - _player->SaveInventoryAndGoldToDB(); - trader->SaveInventoryAndGoldToDB(); - CharacterDatabase.CommitTransaction(); + SQLTransaction trans = CharacterDatabase.BeginTransaction(); + _player->SaveInventoryAndGoldToDB(trans); + trader->SaveInventoryAndGoldToDB(trans); + CharacterDatabase.CommitTransaction(trans); trader->GetSession()->SendTradeStatus(TRADE_STATUS_TRADE_COMPLETE); SendTradeStatus(TRADE_STATUS_TRADE_COMPLETE); diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp index a28b76e3190..fb702947855 100644 --- a/src/server/game/Server/WorldSession.cpp +++ b/src/server/game/Server/WorldSession.cpp @@ -625,11 +625,11 @@ void WorldSession::SetAccountData(AccountDataType type, time_t time_, std::strin { uint32 acc = GetAccountId(); - CharacterDatabase.BeginTransaction (); - CharacterDatabase.PExecute("DELETE FROM account_data WHERE account='%u' AND type='%u'", acc, type); + SQLTransaction trans = CharacterDatabase.BeginTransaction(); + trans->PAppend("DELETE FROM account_data WHERE account='%u' AND type='%u'", acc, type); CharacterDatabase.escape_string(data); - CharacterDatabase.PExecute("INSERT INTO account_data VALUES ('%u','%u','%u','%s')", acc, type, (uint32)time_, data.c_str()); - CharacterDatabase.CommitTransaction (); + trans->PAppend("INSERT INTO account_data VALUES ('%u','%u','%u','%s')", acc, type, (uint32)time_, data.c_str()); + CharacterDatabase.CommitTransaction(trans); } else { @@ -637,11 +637,11 @@ void WorldSession::SetAccountData(AccountDataType type, time_t time_, std::strin if (!m_GUIDLow) return; - CharacterDatabase.BeginTransaction (); - CharacterDatabase.PExecute("DELETE FROM character_account_data WHERE guid='%u' AND type='%u'", m_GUIDLow, type); + SQLTransaction trans = CharacterDatabase.BeginTransaction(); + trans->PAppend("DELETE FROM character_account_data WHERE guid='%u' AND type='%u'", m_GUIDLow, type); CharacterDatabase.escape_string(data); - CharacterDatabase.PExecute("INSERT INTO character_account_data VALUES ('%u','%u','%u','%s')", m_GUIDLow, type, (uint32)time_, data.c_str()); - CharacterDatabase.CommitTransaction (); + trans->PAppend("INSERT INTO character_account_data VALUES ('%u','%u','%u','%s')", m_GUIDLow, type, (uint32)time_, data.c_str()); + CharacterDatabase.CommitTransaction(trans); } m_accountData[type].Time = time_; @@ -689,7 +689,7 @@ void WorldSession::SendTutorialsData() SendPacket(&data); } -void WorldSession::SaveTutorialsData() +void WorldSession::SaveTutorialsData(SQLTransaction& trans) { if (!m_TutorialsChanged) return; @@ -701,14 +701,10 @@ void WorldSession::SaveTutorialsData() Rows = result->Fetch()[0].GetUInt32(); if (Rows) - { - CharacterDatabase.PExecute("UPDATE character_tutorial SET tut0='%u', tut1='%u', tut2='%u', tut3='%u', tut4='%u', tut5='%u', tut6='%u', tut7='%u' WHERE account = '%u'", + trans->PAppend("UPDATE character_tutorial SET tut0='%u', tut1='%u', tut2='%u', tut3='%u', tut4='%u', tut5='%u', tut6='%u', tut7='%u' WHERE account = '%u'", m_Tutorials[0], m_Tutorials[1], m_Tutorials[2], m_Tutorials[3], m_Tutorials[4], m_Tutorials[5], m_Tutorials[6], m_Tutorials[7], GetAccountId()); - } else - { - CharacterDatabase.PExecute("INSERT INTO character_tutorial (account,tut0,tut1,tut2,tut3,tut4,tut5,tut6,tut7) VALUES ('%u', '%u', '%u', '%u', '%u', '%u', '%u', '%u', '%u')", GetAccountId(), m_Tutorials[0], m_Tutorials[1], m_Tutorials[2], m_Tutorials[3], m_Tutorials[4], m_Tutorials[5], m_Tutorials[6], m_Tutorials[7]); - } + trans->PAppend("INSERT INTO character_tutorial (account,tut0,tut1,tut2,tut3,tut4,tut5,tut6,tut7) VALUES ('%u', '%u', '%u', '%u', '%u', '%u', '%u', '%u', '%u')", GetAccountId(), m_Tutorials[0], m_Tutorials[1], m_Tutorials[2], m_Tutorials[3], m_Tutorials[4], m_Tutorials[5], m_Tutorials[6], m_Tutorials[7]); m_TutorialsChanged = false; } @@ -994,7 +990,7 @@ void WorldSession::ProcessQueryCallbacks() //! HandleAddFriendOpcode if (m_addFriendCallback.IsReady()) { - const std::string& param = m_addFriendCallback.GetParam(); + std::string param = m_addFriendCallback.GetParam(); m_addFriendCallback.GetResult(result); HandleAddFriendOpcodeCallBack(result, param); m_addFriendCallback.FreeResult(); @@ -1003,7 +999,7 @@ void WorldSession::ProcessQueryCallbacks() //- HandleCharRenameOpcode if (m_charRenameCallback.IsReady()) { - const std::string& param = m_charRenameCallback.GetParam(); + std::string param = m_charRenameCallback.GetParam(); m_charRenameCallback.GetResult(result); HandleChangePlayerNameOpcodeCallBack(result, param); m_charRenameCallback.FreeResult(); diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h index 26bfbcf7b1f..75aff32af5d 100644 --- a/src/server/game/Server/WorldSession.h +++ b/src/server/game/Server/WorldSession.h @@ -229,7 +229,7 @@ class WorldSession void LoadAccountData(QueryResult_AutoPtr result, uint32 mask); void LoadTutorialsData(); void SendTutorialsData(); - void SaveTutorialsData(); + void SaveTutorialsData(SQLTransaction& trans); uint32 GetTutorialInt(uint32 intId) { return m_Tutorials[intId]; @@ -250,8 +250,6 @@ class WorldSession void SendAuctionCommandResult(uint32 auctionId, uint32 Action, uint32 ErrorCode, uint32 bidError = 0); void SendAuctionBidderNotification(uint32 location, uint32 auctionId, uint64 bidder, uint32 bidSum, uint32 diff, uint32 item_template); void SendAuctionOwnerNotification(AuctionEntry * auction); - void SendAuctionOutbiddedMail(AuctionEntry * auction, uint32 newPrice); - void SendAuctionCancelledToBidderMail(AuctionEntry* auction); //Item Enchantment void SendEnchantmentLog(uint64 Target, uint64 Caster,uint32 ItemID,uint32 SpellID); diff --git a/src/server/game/Tools/PlayerDump.cpp b/src/server/game/Tools/PlayerDump.cpp index 4fed5faa7dd..5dd0ed97dc7 100644 --- a/src/server/game/Tools/PlayerDump.cpp +++ b/src/server/game/Tools/PlayerDump.cpp @@ -369,7 +369,7 @@ DumpReturn PlayerDumpWriter::WriteDump(const std::string& file, uint32 guid) } // Reading - High-level functions -#define ROLLBACK(DR) {CharacterDatabase.RollbackTransaction(); fclose(fin); return (DR);} +#define ROLLBACK(DR) {fclose(fin); return (DR);} void fixNULLfields(std::string &line) { @@ -436,7 +436,7 @@ DumpReturn PlayerDumpReader::LoadDump(const std::string& file, uint32 account, s typedef PetIds::value_type PetIdsPair; PetIds petids; - CharacterDatabase.BeginTransaction(); + SQLTransaction trans = CharacterDatabase.BeginTransaction(); while (!feof(fin)) { if (!fgets(buf, 32000, fin)) @@ -629,10 +629,10 @@ DumpReturn PlayerDumpReader::LoadDump(const std::string& file, uint32 account, s fixNULLfields(line); - CharacterDatabase.Execute(line.c_str()); + trans->Append(line.c_str()); } - CharacterDatabase.CommitTransaction(); + CharacterDatabase.CommitTransaction(trans); sObjectMgr.m_hiItemGuid += items.size(); sObjectMgr.m_mailid += mails.size(); diff --git a/src/server/shared/Database/DatabaseEnv.h b/src/server/shared/Database/DatabaseEnv.h index a878a358760..d6aa7dc9b41 100644 --- a/src/server/shared/Database/DatabaseEnv.h +++ b/src/server/shared/Database/DatabaseEnv.h @@ -30,8 +30,10 @@ #include "DatabaseWorkerPool.h" #include "MySQLThreading.h" +#include "Transaction.h" typedef DatabaseWorkerPool DatabaseType; + #define _LIKE_ "LIKE" #define _TABLE_SIM_ "`" #define _CONCAT3_(A,B,C) "CONCAT( " A " , " B " , " C " )" diff --git a/src/server/shared/Database/DatabaseWorkerPool.cpp b/src/server/shared/Database/DatabaseWorkerPool.cpp index 538a3535efd..654caf33511 100644 --- a/src/server/shared/Database/DatabaseWorkerPool.cpp +++ b/src/server/shared/Database/DatabaseWorkerPool.cpp @@ -16,7 +16,6 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "DatabaseEnv.h" #include "DatabaseWorkerPool.h" #include "MySQLConnection.h" #include "DatabaseEnv.h" @@ -183,43 +182,25 @@ QueryResult_AutoPtr DatabaseWorkerPool::PQuery(const char* sql, ...) return Query(szQuery); } -void DatabaseWorkerPool::BeginTransaction() +SQLTransaction DatabaseWorkerPool::BeginTransaction() { - ACE_Guard<ACE_Thread_Mutex> guard(m_transQueues_mtx); - ACE_Based::Thread* tranThread = ACE_Based::Thread::current(); // owner of this transaction - TransactionQueues::iterator itr = m_tranQueues.find(tranThread); - if (itr != m_tranQueues.end() && itr->second != NULL) - { - itr->second->ForcefulDelete(); - delete itr->second; - } - m_tranQueues[tranThread] = new TransactionTask(); - return; + return SQLTransaction(new Transaction); } -void DatabaseWorkerPool::RollbackTransaction() +void DatabaseWorkerPool::CommitTransaction(SQLTransaction transaction) { - ACE_Guard<ACE_Thread_Mutex> guard(m_transQueues_mtx); - ACE_Based::Thread* tranThread = ACE_Based::Thread::current(); // owner of this transaction - TransactionQueues::iterator itr = m_tranQueues.find(tranThread); - if (itr != m_tranQueues.end() && itr->second != NULL) + #ifdef _DEBUG + if (transaction->GetSize() == 0) { - itr->second->ForcefulDelete(); - delete itr->second; - itr->second = NULL; + sLog.outError("Transaction contains 0 queries"); + return; } -} - -void DatabaseWorkerPool::CommitTransaction() -{ - ACE_Guard<ACE_Thread_Mutex> guard(m_transQueues_mtx); - ACE_Based::Thread* tranThread = ACE_Based::Thread::current(); // owner of this transaction - TransactionQueues::iterator itr = m_tranQueues.find(tranThread); - if (itr != m_tranQueues.end() && itr->second != NULL) + if (transaction->GetSize() == 1) { - Enqueue(itr->second); - itr->second = NULL; + sLog.outDetail("Warning: Transaction only holds 1 query, consider removing Transaction context in code."); } + #endif + Enqueue(new TransactionTask(transaction)); } ACE_Future<QueryResult_AutoPtr> DatabaseWorkerPool::AsyncQuery(const char* sql) @@ -258,7 +239,7 @@ MySQLConnection* DatabaseWorkerPool::GetConnection() ACE_Guard<ACE_Thread_Mutex> guard(m_connectionMap_mtx); itr = m_sync_connections.find(ACE_Based::Thread::current()); if (itr != m_sync_connections.end()) - return itr->second; + conn = itr->second; } /*! Bundled threads */ conn = m_bundle_conn; diff --git a/src/server/shared/Database/DatabaseWorkerPool.h b/src/server/shared/Database/DatabaseWorkerPool.h index 6443d05b0dd..2a1350888a2 100644 --- a/src/server/shared/Database/DatabaseWorkerPool.h +++ b/src/server/shared/Database/DatabaseWorkerPool.h @@ -28,6 +28,7 @@ #include "QueryResult.h" #include "Callback.h" #include "MySQLConnection.h" +#include "Transaction.h" enum MySQLThreadBundle { @@ -73,9 +74,8 @@ class DatabaseWorkerPool ACE_Future<QueryResult_AutoPtr> AsyncPQuery(const char* sql, ...); QueryResultHolderFuture DelayQueryHolder(SQLQueryHolder* holder); - void BeginTransaction(); - void RollbackTransaction(); - void CommitTransaction(); + SQLTransaction BeginTransaction(); + void CommitTransaction(SQLTransaction transaction); void escape_string(std::string& str) { @@ -117,8 +117,6 @@ class DatabaseWorkerPool MySQLConnection* m_bundle_conn; //! Bundled connection (see Database.ThreadBundleMask config) AtomicUInt m_connections; //! Counter of MySQL connections; std::string m_infoString; //! Infostring that is passed on to child connections. - TransactionQueues m_tranQueues; //! Transaction queues from diff. threads - ACE_Thread_Mutex m_transQueues_mtx; //! To guard m_transQueues }; #endif diff --git a/src/server/shared/Database/SQLOperation.cpp b/src/server/shared/Database/SQLOperation.cpp index 1cd45a4c0b6..a3eda4b7239 100644 --- a/src/server/shared/Database/SQLOperation.cpp +++ b/src/server/shared/Database/SQLOperation.cpp @@ -16,9 +16,9 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "DatabaseEnv.h" #include "SQLOperation.h" #include "MySQLConnection.h" +#include "Log.h" /*! Basic, ad-hoc queries. */ BasicStatementTask::BasicStatementTask(const char* sql) : @@ -53,53 +53,6 @@ bool BasicStatementTask::Execute() return m_conn->Execute(m_sql); } -/*! Transactions. */ -TransactionTask::TransactionTask() -{ -} - -TransactionTask::~TransactionTask() -{ - -} - -void TransactionTask::ForcefulDelete() -{ - while (!m_queries.empty()) - { - free((void*)const_cast<char*>(m_queries.front())); - m_queries.pop(); - } -} - -bool TransactionTask::Execute() -{ - if (m_queries.empty()) - return false; - - const char* sql; - - m_conn->BeginTransaction(); - while (!m_queries.empty()) - { - sql = m_queries.front(); - if (!m_conn->Execute(sql)) - { - free((void*)const_cast<char*>(sql)); - m_queries.pop(); - m_conn->RollbackTransaction(); - ForcefulDelete(); - return false; - } - - free((void*)const_cast<char*>(sql)); - m_queries.pop(); - } - - m_conn->CommitTransaction(); - return true; -} - bool SQLQueryHolder::SetQuery(size_t index, const char *sql) { if (m_queries.size() <= index) diff --git a/src/server/shared/Database/SQLOperation.h b/src/server/shared/Database/SQLOperation.h index a8238802e31..0c5fe08d94e 100644 --- a/src/server/shared/Database/SQLOperation.h +++ b/src/server/shared/Database/SQLOperation.h @@ -59,19 +59,7 @@ class BasicStatementTask : public SQLOperation QueryResultFuture m_result; }; -/*! Transactions */ -class TransactionTask : public SQLOperation -{ - public: - TransactionTask(); - ~TransactionTask(); - void ForcefulDelete(); - - bool Execute(); - private: - std::queue<char*> m_queries; -}; class SQLQueryHolder { diff --git a/src/server/shared/Database/Transaction.cpp b/src/server/shared/Database/Transaction.cpp new file mode 100644 index 00000000000..a364728b2d0 --- /dev/null +++ b/src/server/shared/Database/Transaction.cpp @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Transaction.h" + +void Transaction::Append(const char* sql) +{ + m_queries.push(strdup(sql)); +} + +void Transaction::PAppend(const char* sql, ...) +{ + va_list ap; + char szQuery [MAX_QUERY_LEN]; + va_start(ap, sql); + int res = vsnprintf(szQuery, MAX_QUERY_LEN, sql, ap); + va_end(ap); + + Append(szQuery); +} + +void Transaction::Cleanup() +{ + while (!m_queries.empty()) + { + free((void*)const_cast<char*>(m_queries.front())); + m_queries.pop(); + } +} + +bool TransactionTask::Execute() +{ + std::queue<char*>& queries = m_trans->m_queries; + if (queries.empty()) + return false; + + const char* sql; + + m_conn->BeginTransaction(); + while (!queries.empty()) + { + sql = queries.front(); + if (!m_conn->Execute(sql)) + { + free((void*)const_cast<char*>(sql)); + queries.pop(); + m_conn->RollbackTransaction(); + return false; + } + + free((void*)const_cast<char*>(sql)); + queries.pop(); + } + + m_conn->CommitTransaction(); + return true; +} diff --git a/src/server/shared/Database/Transaction.h b/src/server/shared/Database/Transaction.h new file mode 100644 index 00000000000..e94ca053e32 --- /dev/null +++ b/src/server/shared/Database/Transaction.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _TRANSACTION_H +#define _TRANSACTION_H + +/*! Transactions, high level class. */ +class Transaction +{ + friend class TransactionTask; + public: + ~Transaction() { Cleanup(); } + + void Append(const char* sql); + void PAppend(const char* sql, ...); + + size_t GetSize() { return m_queries.size(); } + + protected: + void Cleanup(); + std::queue<char*> m_queries; + + private: + bool m_actioned; +}; +typedef ACE_Refcounted_Auto_Ptr<Transaction, ACE_Null_Mutex> SQLTransaction; + +/*! Low level class*/ +class TransactionTask : public SQLOperation +{ + friend class DatabaseWorkerPool; + friend class DatabaseWorker; + + public: + TransactionTask(SQLTransaction trans) : m_trans(trans) {} ; + ~TransactionTask(){}; + + protected: + bool Execute(); + + SQLTransaction m_trans; +}; + +#endif
\ No newline at end of file |