00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <cassert>
00022 #include <time.h>
00023
00024 #include "account-server/dalstorage.hpp"
00025
00026 #include "point.h"
00027 #include "account-server/account.hpp"
00028 #include "account-server/dalstoragesql.hpp"
00029 #include "chat-server/chatchannel.hpp"
00030 #include "chat-server/guild.hpp"
00031 #include "chat-server/post.hpp"
00032 #include "common/configuration.hpp"
00033 #include "dal/dalexcept.h"
00034 #include "dal/dataproviderfactory.h"
00035 #include "utils/functors.h"
00036 #include "utils/logger.h"
00037 #include "utils/xml.hpp"
00038
00039
00040 #define DEFAULT_ITEM_FILE "data/items.xml"
00041
00042
00043 #define DB_VERSION_PARAMETER "database_version"
00044 #define SUPPORTED_DB_VERSION "3"
00045
00046
00050 DALStorage::DALStorage()
00051 : mDb(dal::DataProviderFactory::createDataProvider()),
00052 mItemDbVersion(0)
00053 {
00054 }
00055
00059 DALStorage::~DALStorage()
00060 {
00061 if (mDb->isConnected()) {
00062 close();
00063 }
00064 delete mDb;
00065 }
00066
00071 void DALStorage::open()
00072 {
00073
00074 if (mDb->isConnected())
00075 {
00076 return;
00077 }
00078
00079 using namespace dal;
00080
00081 try {
00082
00083 mDb->connect();
00084
00085
00086 std::string dbversion = getWorldStateVar(DB_VERSION_PARAMETER);
00087 if (dbversion != SUPPORTED_DB_VERSION)
00088 {
00089 std::ostringstream errmsg;
00090 errmsg << "Database version is not supported. " <<
00091 "Needed version: '" << SUPPORTED_DB_VERSION <<
00092 "', current version: '" << dbversion << "'";
00093 throw errmsg.str();
00094 }
00095
00096
00097 SyncDatabase();
00098
00099
00100 std::ostringstream sql;
00101 sql << "DELETE FROM " << ONLINE_USERS_TBL_NAME;
00102 mDb->execSql(sql.str());
00103 }
00104 catch (const DbConnectionFailure& e) {
00105 std::ostringstream errmsg;
00106 errmsg << "(DALStorage::open #1) Unable to connect to the database: "
00107 << e.what();
00108 throw errmsg.str();
00109 }
00110 }
00111
00115 void DALStorage::close()
00116 {
00117 mDb->disconnect();
00118 }
00119
00120 Account *DALStorage::getAccountBySQL(const std::string &query)
00121 {
00122 try {
00123 const dal::RecordSet &accountInfo = mDb->execSql(query);
00124
00125
00126
00127 if (accountInfo.isEmpty())
00128 {
00129 return NULL;
00130 }
00131
00132
00133
00134 string_to< unsigned > toUint;
00135 unsigned id = toUint(accountInfo(0, 0));
00136
00137
00138
00139 Account *account = new Account(id);
00140 account->setName(accountInfo(0, 1));
00141 account->setPassword(accountInfo(0, 2));
00142 account->setEmail(accountInfo(0, 3));
00143 account->setRegistrationDate(toUint(accountInfo(0, 6)));
00144 account->setLastLogin(toUint(accountInfo(0, 7)));
00145
00146 int level = toUint(accountInfo(0, 4));
00147
00148 if (level == AL_BANNED
00149 || time(NULL) <= (int) toUint(accountInfo(0, 5)))
00150 {
00151 account->setLevel(AL_BANNED);
00152
00153 return account;
00154 }
00155 account->setLevel(level);
00156
00157
00158 std::ostringstream sql;
00159 sql << "select id from " << CHARACTERS_TBL_NAME << " where user_id = '"
00160 << id << "';";
00161 const dal::RecordSet &charInfo = mDb->execSql(sql.str());
00162
00163 if (!charInfo.isEmpty())
00164 {
00165 int size = charInfo.rows();
00166 Characters characters;
00167
00168 LOG_DEBUG("Account "<< id << " has " << size << " character(s) in database.");
00169
00170
00171 std::vector< unsigned > characterIDs;
00172 for (int k = 0; k < size; ++k)
00173 {
00174 characterIDs.push_back(toUint(charInfo(k, 0)));
00175 }
00176
00177 for (int k = 0; k < size; ++k)
00178 {
00179 if (Character *ptr = getCharacter(characterIDs[k], account))
00180 {
00181 characters.push_back(ptr);
00182 }
00183 else
00184 {
00185 LOG_ERROR("Failed to get character " << characterIDs[k] << " for account " << id << '.');
00186 }
00187 }
00188
00189 account->setCharacters(characters);
00190 }
00191
00192 return account;
00193 }
00194 catch (const dal::DbSqlQueryExecFailure &e)
00195 {
00196 LOG_ERROR("DALStorage::getAccountBySQL: " << e.what());
00197 return NULL;
00198 }
00199 }
00200
00204 Account *DALStorage::getAccount(const std::string &userName)
00205 {
00206 std::ostringstream sql;
00207 sql << "select * from " << ACCOUNTS_TBL_NAME << " where username = \"" << userName << "\";";
00208 return getAccountBySQL(sql.str());
00209 }
00210
00214 Account *DALStorage::getAccount(int accountID)
00215 {
00216 std::ostringstream sql;
00217 sql << "select * from " << ACCOUNTS_TBL_NAME << " where id = '" << accountID << "';";
00218 return getAccountBySQL(sql.str());
00219 }
00220
00221 Character *DALStorage::getCharacterBySQL(const std::string &query, Account *owner)
00222 {
00223 Character *character;
00224
00225
00226
00227 string_to< unsigned > toUint;
00228
00229 try {
00230 const dal::RecordSet &charInfo = mDb->execSql(query);
00231
00232
00233
00234 if (charInfo.isEmpty())
00235 {
00236 return NULL;
00237 }
00238
00239
00240
00241 string_to< unsigned short > toUshort;
00242
00243 character = new Character(charInfo(0, 2), toUint(charInfo(0, 0)));
00244 character->setGender(toUshort(charInfo(0, 3)));
00245 character->setHairStyle(toUshort(charInfo(0, 4)));
00246 character->setHairColor(toUshort(charInfo(0, 5)));
00247 character->setLevel(toUshort(charInfo(0, 6)));
00248 character->setCharacterPoints(toUshort(charInfo(0, 7)));
00249 character->setCorrectionPoints(toUshort(charInfo(0, 8)));
00250 character->getPossessions().money = toUint(charInfo(0, 9));
00251 Point pos(toUshort(charInfo(0, 10)), toUshort(charInfo(0, 11)));
00252 character->setPosition(pos);
00253 for (int i = 0; i < CHAR_ATTR_NB; ++i)
00254 {
00255 character->setAttribute(CHAR_ATTR_BEGIN + i,
00256 toUshort(charInfo(0, 13 + i)));
00257 }
00258
00259 int mapId = toUint(charInfo(0, 12));
00260 if (mapId > 0)
00261 {
00262 character->setMapId(mapId);
00263 }
00264 else
00265 {
00266
00267
00268 character->setMapId(Configuration::getValue("defaultMap", 1));
00269 }
00270
00271
00272
00273 if (owner)
00274 {
00275 character->setAccount(owner);
00276 }
00277 else
00278 {
00279 int id = toUint(charInfo(0, 1));
00280 character->setAccountID(id);
00281 std::ostringstream s;
00282 s << "select level from " << ACCOUNTS_TBL_NAME
00283 << " where id = '" << id << "';";
00284 const dal::RecordSet &levelInfo = mDb->execSql(s.str());
00285 character->setAccountLevel(toUint(levelInfo(0, 0)), true);
00286 }
00287
00288
00289 std::ostringstream s;
00290 s << "SELECT skill_id, skill_exp "
00291 << "FROM " << CHAR_SKILLS_TBL_NAME << " "
00292 << "WHERE char_id = " << character->getDatabaseID();
00293
00294 const dal::RecordSet &skillInfo = mDb->execSql(s.str());
00295 if (!skillInfo.isEmpty())
00296 {
00297 const unsigned int nRows = skillInfo.rows();
00298 for (unsigned int row = 0; row < nRows; row++)
00299 {
00300 character->setExperience(
00301 toUint(skillInfo(row, 0)),
00302 toUint(skillInfo(row, 1)));
00303 }
00304 }
00305 }
00306 catch (const dal::DbSqlQueryExecFailure &e)
00307 {
00308 LOG_ERROR("(DALStorage::getCharacter #1) SQL query failure: " << e.what());
00309 return NULL;
00310 }
00311
00312 try
00313 {
00314 std::ostringstream sql;
00315 sql << " select * from " << INVENTORIES_TBL_NAME << " where owner_id = '"
00316 << character->getDatabaseID() << "' order by slot asc;";
00317
00318 const dal::RecordSet &itemInfo = mDb->execSql(sql.str());
00319 if (!itemInfo.isEmpty())
00320 {
00321 Possessions &poss = character->getPossessions();
00322 unsigned nextSlot = 0;
00323
00324 for (int k = 0, size = itemInfo.rows(); k < size; ++k)
00325 {
00326 unsigned slot = toUint(itemInfo(k, 2));
00327 if (slot < EQUIPMENT_SLOTS)
00328 {
00329 poss.equipment[slot] = toUint(itemInfo(k, 3));
00330 }
00331 else
00332 {
00333 slot -= 32;
00334 if (slot >= INVENTORY_SLOTS || slot < nextSlot)
00335 {
00336 LOG_ERROR("(DALStorage::getCharacter #2) Corrupted inventory.");
00337 break;
00338 }
00339 InventoryItem item;
00340 if (slot != nextSlot)
00341 {
00342 item.itemId = 0;
00343 item.amount = slot - nextSlot;
00344 poss.inventory.push_back(item);
00345 }
00346 item.itemId = toUint(itemInfo(k, 3));
00347 item.amount = toUint(itemInfo(k, 4));
00348 poss.inventory.push_back(item);
00349 nextSlot = slot + 1;
00350 }
00351 }
00352 }
00353 }
00354 catch (const dal::DbSqlQueryExecFailure &e)
00355 {
00356 LOG_ERROR("(DALStorage::getCharacter #2) SQL query failure: " << e.what());
00357 return NULL;
00358 }
00359
00360 return character;
00361 }
00362
00366 Character *DALStorage::getCharacter(int id, Account *owner)
00367 {
00368 std::ostringstream sql;
00369 sql << "select * from " << CHARACTERS_TBL_NAME << " where id = '" << id << "';";
00370 return getCharacterBySQL(sql.str(), owner);
00371 }
00372
00373 Character *DALStorage::getCharacter(const std::string &name)
00374 {
00375 std::ostringstream sql;
00376 sql << "select * from " << CHARACTERS_TBL_NAME << " where name = '" << name << "';";
00377 return getCharacterBySQL(sql.str(), NULL);
00378 }
00379
00380 #if 0
00381
00384 std::list<std::string>
00385 DALStorage::getEmailList()
00386 {
00387 std::list <std::string> emailList;
00388
00389 try {
00390 std::string sql("select email from ");
00391 sql += ACCOUNTS_TBL_NAME;
00392 sql += ";";
00393 const dal::RecordSet& accountInfo = mDb->execSql(sql);
00394
00395
00396
00397 if (accountInfo.isEmpty()) {
00398 return emailList;
00399 }
00400 for (unsigned int i = 0; i < accountInfo.rows(); i++)
00401 {
00402
00403 emailList.push_front(accountInfo(i, 0));
00404 }
00405 }
00406 catch (const dal::DbSqlQueryExecFailure& e) {
00407
00408 LOG_ERROR("(DALStorage::getEmailList) SQL query failure: " << e.what());
00409 }
00410
00411 return emailList;
00412 }
00413 #endif
00414
00415 bool DALStorage::doesUserNameExist(const std::string &name)
00416 {
00417 try {
00418 std::ostringstream sql;
00419 sql << "select count(username) from " << ACCOUNTS_TBL_NAME
00420 << " where username = \"" << name << "\";";
00421 const dal::RecordSet &accountInfo = mDb->execSql(sql.str());
00422
00423 std::istringstream ssStream(accountInfo(0, 0));
00424 unsigned int iReturn = 1;
00425 ssStream >> iReturn;
00426 return iReturn != 0;
00427 } catch (const std::exception &e) {
00428
00429 LOG_ERROR("(DALStorage::doesUserNameExist) SQL query failure: " << e.what());
00430 }
00431
00432 return true;
00433 }
00434
00439 bool DALStorage::doesEmailAddressExist(const std::string &email)
00440 {
00441 try {
00442 std::ostringstream sql;
00443 sql << "select count(email) from " << ACCOUNTS_TBL_NAME
00444 << " where upper(email) = upper(\"" << email << "\");";
00445 const dal::RecordSet &accountInfo = mDb->execSql(sql.str());
00446
00447 std::istringstream ssStream(accountInfo(0, 0));
00448 unsigned int iReturn = 1;
00449 ssStream >> iReturn;
00450 return iReturn != 0;
00451 } catch (const std::exception &e) {
00452
00453 LOG_ERROR("(DALStorage::doesEmailAddressExist) SQL query failure: " << e.what());
00454 }
00455
00456 return true;
00457 }
00458
00463 bool DALStorage::doesCharacterNameExist(const std::string& name)
00464 {
00465 try {
00466 std::ostringstream sql;
00467 sql << "select count(name) from " << CHARACTERS_TBL_NAME
00468 << " where name = \"" << name << "\";";
00469 const dal::RecordSet &accountInfo = mDb->execSql(sql.str());
00470
00471 std::istringstream ssStream(accountInfo(0, 0));
00472 int iReturn = 1;
00473 ssStream >> iReturn;
00474 return iReturn != 0;
00475 } catch (const std::exception &e) {
00476
00477 LOG_ERROR("(DALStorage::doesCharacterNameExist) SQL query failure: "
00478 << e.what());
00479 }
00480
00481 return true;
00482 }
00483
00484 bool DALStorage::updateCharacter(Character *character,
00485 bool startTransaction)
00486 {
00487
00488 if (startTransaction)
00489 {
00490 mDb->beginTransaction();
00491 }
00492 try
00493 {
00494 std::ostringstream sqlUpdateCharacterInfo;
00495 sqlUpdateCharacterInfo
00496 << "update " << CHARACTERS_TBL_NAME << " "
00497 << "set "
00498 << "gender = '" << character->getGender() << "', "
00499 << "hair_style = '" << character->getHairStyle() << "', "
00500 << "hair_color = '" << character->getHairColor() << "', "
00501 << "level = '" << character->getLevel() << "', "
00502 << "char_pts = '" << character->getCharacterPoints() << "', "
00503 << "correct_pts = '"<< character->getCorrectionPoints() << "', "
00504 << "money = '" << character->getPossessions().money << "', "
00505 << "x = '" << character->getPosition().x << "', "
00506 << "y = '" << character->getPosition().y << "', "
00507 << "map_id = '" << character->getMapId() << "', "
00508 << "str = '" << character->getAttribute(CHAR_ATTR_STRENGTH) << "', "
00509 << "agi = '" << character->getAttribute(CHAR_ATTR_AGILITY) << "', "
00510 << "dex = '" << character->getAttribute(CHAR_ATTR_DEXTERITY) << "', "
00511 << "vit = '" << character->getAttribute(CHAR_ATTR_VITALITY) << "', "
00512 #if defined(MYSQL_SUPPORT) || defined(POSTGRESQL_SUPPORT)
00513 << "`int` = '"
00514 #else
00515 << "int = '"
00516 #endif
00517 << character->getAttribute(CHAR_ATTR_INTELLIGENCE) << "', "
00518 << "will = '" << character->getAttribute(CHAR_ATTR_WILLPOWER) << "' "
00519 << "where id = '" << character->getDatabaseID() << "';";
00520
00521 mDb->execSql(sqlUpdateCharacterInfo.str());
00522 }
00523 catch (const dal::DbSqlQueryExecFailure& e)
00524 {
00525
00526 if (startTransaction)
00527 {
00528 mDb->rollbackTransaction();
00529 }
00530 LOG_ERROR("(DALStorage::updateCharacter #1) SQL query failure: " << e.what());
00531 return false;
00532 }
00533
00537 try
00538 {
00539 for (unsigned int skill_id = 0; skill_id < CHAR_SKILL_NB; skill_id++)
00540 {
00541 updateExperience(character->getDatabaseID(), skill_id,
00542 character->getExperience(skill_id));
00543 }
00544 }
00545 catch (const dal::DbSqlQueryExecFailure& e)
00546 {
00547
00548 if (startTransaction)
00549 {
00550 mDb->rollbackTransaction();
00551 }
00552 LOG_ERROR("(DALStorage::updateCharacter #2) SQL query failure: " << e.what());
00553 return false;
00554 }
00555
00556
00561
00562 try
00563 {
00564 std::ostringstream sqlDeleteCharacterInventory;
00565 sqlDeleteCharacterInventory
00566 << "delete from " << INVENTORIES_TBL_NAME
00567 << " where owner_id = '" << character->getDatabaseID() << "';";
00568 mDb->execSql(sqlDeleteCharacterInventory.str());
00569 }
00570 catch (const dal::DbSqlQueryExecFailure& e)
00571 {
00572
00573 if (startTransaction)
00574 {
00575 mDb->rollbackTransaction();
00576 }
00577 LOG_ERROR("(DALStorage::updateCharacter #3) SQL query failure: " << e.what());
00578 return false;
00579 }
00580
00581
00582 try
00583 {
00584 std::ostringstream sql;
00585
00586 sql << "insert into " << INVENTORIES_TBL_NAME
00587 << " (owner_id, slot, class_id, amount) values ("
00588 << character->getDatabaseID() << ", ";
00589 std::string base = sql.str();
00590
00591 const Possessions &poss = character->getPossessions();
00592
00593 for (int j = 0; j < EQUIPMENT_SLOTS; ++j)
00594 {
00595 int v = poss.equipment[j];
00596 if (!v) continue;
00597 sql.str(std::string());
00598 sql << base << j << ", " << v << ", 1);";
00599 mDb->execSql(sql.str());
00600 }
00601
00602 int slot = 32;
00603 for (std::vector< InventoryItem >::const_iterator j = poss.inventory.begin(),
00604 j_end = poss.inventory.end(); j != j_end; ++j)
00605 {
00606 int v = j->itemId;
00607 if (!v)
00608 {
00609 slot += j->amount;
00610 continue;
00611 }
00612 sql.str(std::string());
00613 sql << base << slot << ", " << v << ", " << unsigned(j->amount) << ");";
00614 mDb->execSql(sql.str());
00615 ++slot;
00616 }
00617
00618 }
00619 catch (const dal::DbSqlQueryExecFailure& e)
00620 {
00621
00622 if (startTransaction)
00623 {
00624 mDb->rollbackTransaction();
00625 }
00626 LOG_ERROR("(DALStorage::updateCharacter #4) SQL query failure: " << e.what());
00627 return false;
00628 }
00629
00630 if (startTransaction)
00631 {
00632 mDb->commitTransaction();
00633 }
00634 return true;
00635 }
00636
00641 void DALStorage::flushSkill(const Character* const character,
00642 const int skill_id )
00643 {
00644 updateExperience(character->getDatabaseID(), skill_id,
00645 character->getExperience(skill_id));
00646 }
00647
00651 void DALStorage::addAccount(Account *account)
00652 {
00653 assert(account->getCharacters().size() == 0);
00654
00655 using namespace dal;
00656
00657 mDb->beginTransaction();
00658 try
00659 {
00660
00661 std::ostringstream sql1;
00662 sql1 << "insert into " << ACCOUNTS_TBL_NAME
00663 << " (username, password, email, level, banned, registration, lastlogin)"
00664 << " values (\""
00665 << account->getName() << "\", \""
00666 << account->getPassword() << "\", \""
00667 << account->getEmail() << "\", "
00668 << account->getLevel() << ", 0, "
00669 << account->getRegistrationDate() << ", "
00670 << account->getLastLogin() << ");";
00671 mDb->execSql(sql1.str());
00672 account->setID(mDb->getLastId());
00673
00674 mDb->commitTransaction();
00675 }
00676 catch (const dal::DbSqlQueryExecFailure &e)
00677 {
00678 LOG_ERROR("Error in DALStorage::addAccount: " << e.what());
00679 mDb->rollbackTransaction();
00680 }
00681 }
00682
00686 void DALStorage::flush(Account *account)
00687 {
00688 assert(account->getID() >= 0);
00689
00690 using namespace dal;
00691
00692 mDb->beginTransaction();
00693 try
00694 {
00695
00696
00697 std::ostringstream sqlUpdateAccountTable;
00698 sqlUpdateAccountTable
00699 << "update " << ACCOUNTS_TBL_NAME
00700 << " set username = '" << account->getName() << "', "
00701 << "password = '" << account->getPassword() << "', "
00702 << "email = '" << account->getEmail() << "', "
00703 << "level = '" << account->getLevel() << "', "
00704 << "lastlogin = '" << account->getLastLogin() << "' "
00705 << "where id = '" << account->getID() << "';";
00706 mDb->execSql(sqlUpdateAccountTable.str());
00707
00708
00709 Characters &characters = account->getCharacters();
00710
00711
00712 for (Characters::const_iterator it = characters.begin(),
00713 it_end = characters.end(); it != it_end; ++it)
00714 {
00715 if ((*it)->getDatabaseID() >= 0)
00716 {
00717
00718
00719
00720 updateCharacter(*it, false);
00721 }
00722 else
00723 {
00724 std::ostringstream sqlInsertCharactersTable;
00725
00726
00727
00728 sqlInsertCharactersTable
00729 << "insert into " << CHARACTERS_TBL_NAME
00730 << " (user_id, name, gender, hair_style, hair_color, level, char_pts, correct_pts, money,"
00731 << " x, y, map_id, str, agi, dex, vit, "
00732 #if defined(MYSQL_SUPPORT) || defined(POSTGRESQL_SUPPORT)
00733 << "`int`, "
00734 #else
00735 << "int, "
00736 #endif
00737 << "will ) values ("
00738 << account->getID() << ", \""
00739 << (*it)->getName() << "\", "
00740 << (*it)->getGender() << ", "
00741 << (int)(*it)->getHairStyle() << ", "
00742 << (int)(*it)->getHairColor() << ", "
00743 << (int)(*it)->getLevel() << ", "
00744 << (int)(*it)->getCharacterPoints() << ", "
00745 << (int)(*it)->getCorrectionPoints() << ", "
00746 << (*it)->getPossessions().money << ", "
00747 << (*it)->getPosition().x << ", "
00748 << (*it)->getPosition().y << ", "
00749 << (*it)->getMapId() << ", "
00750 << (*it)->getAttribute(CHAR_ATTR_STRENGTH) << ", "
00751 << (*it)->getAttribute(CHAR_ATTR_AGILITY) << ", "
00752 << (*it)->getAttribute(CHAR_ATTR_DEXTERITY) << ", "
00753 << (*it)->getAttribute(CHAR_ATTR_VITALITY) << ", "
00754 << (*it)->getAttribute(CHAR_ATTR_INTELLIGENCE) << ", "
00755 << (*it)->getAttribute(CHAR_ATTR_WILLPOWER) << " "
00756 << ");";
00757
00758 mDb->execSql(sqlInsertCharactersTable.str());
00759
00760
00761 (*it)->setDatabaseID(mDb->getLastId());
00762
00763
00764 for (unsigned int skill_id = 0; skill_id < CHAR_SKILL_NB; skill_id++)
00765 {
00766 updateExperience((*it)->getDatabaseID(), skill_id,
00767 (*it)->getExperience(skill_id));
00768 }
00769 }
00770 }
00771
00772
00773
00774
00775
00776
00777 string_to<unsigned short> toUint;
00778
00779 std::ostringstream sqlSelectNameIdCharactersTable;
00780 sqlSelectNameIdCharactersTable
00781 << "select name, id from " << CHARACTERS_TBL_NAME
00782 << " where user_id = '" << account->getID() << "';";
00783 const RecordSet& charInMemInfo =
00784 mDb->execSql(sqlSelectNameIdCharactersTable.str());
00785
00786
00787
00788 bool charFound;
00789 for (unsigned int i = 0; i < charInMemInfo.rows(); ++i)
00790 {
00791 charFound = false;
00792 for (Characters::const_iterator it = characters.begin(),
00793 it_end = characters.end(); it != it_end; ++it)
00794 {
00795 if (charInMemInfo(i, 0) == (*it)->getName())
00796 {
00797 charFound = true;
00798 break;
00799 }
00800 }
00801 if (!charFound)
00802 {
00803
00804
00805
00806
00807
00808 unsigned int charId = toUint(charInMemInfo(i, 1));
00809 delCharacter(charId, false);
00810 }
00811 }
00812
00813 mDb->commitTransaction();
00814 }
00815 catch (const std::exception &e)
00816 {
00817 LOG_ERROR("ERROR in DALStorage::flush: " << e.what());
00818 mDb->rollbackTransaction();
00819 }
00820 }
00821
00825 void DALStorage::delAccount(Account *account)
00826 {
00827 account->setCharacters(Characters());
00828 flush(account);
00829
00830
00831 std::ostringstream sql;
00832 sql << "delete from " << ACCOUNTS_TBL_NAME
00833 << " where id = '" << account->getID() << "';";
00834 mDb->execSql(sql.str());
00835 }
00836
00840 void DALStorage::updateLastLogin(const Account *account)
00841 {
00842 std::ostringstream sql;
00843 sql << "UPDATE " << ACCOUNTS_TBL_NAME
00844 << " SET lastlogin = '" << account->getLastLogin() << "'"
00845 << " WHERE id = '" << account->getID() << "';";
00846 mDb->execSql(sql.str());
00847 }
00848
00849 void DALStorage::updateCharacterPoints(const int CharId, const int CharPoints,
00850 const int CorrPoints, const int AttribId, const int AttribValue )
00851 {
00852 std::ostringstream sql;
00853 sql << "UPDATE " << CHARACTERS_TBL_NAME
00854 << " SET char_pts = " << CharPoints << ", "
00855 << " correct_pts = " << CorrPoints << ", ";
00856
00857 switch (AttribId)
00858 {
00859 case CHAR_ATTR_STRENGTH: sql << "str = "; break;
00860 case CHAR_ATTR_AGILITY: sql << "agi = "; break;
00861 case CHAR_ATTR_DEXTERITY: sql << "dex = "; break;
00862 case CHAR_ATTR_VITALITY: sql << "vit = "; break;
00863 case CHAR_ATTR_INTELLIGENCE: sql << "int = "; break;
00864 case CHAR_ATTR_WILLPOWER: sql << "will = "; break;
00865 }
00866 sql << AttribValue
00867 << " WHERE id = " << CharId;
00868
00869 mDb->execSql(sql.str());
00870 }
00871
00872 void DALStorage::updateExperience(const int CharId, const int SkillId,
00873 const int SkillValue)
00874 {
00875 try
00876 {
00877
00878
00879 if (SkillValue == 0)
00880 {
00881 std::ostringstream sql;
00882 sql << "DELETE FROM " << CHAR_SKILLS_TBL_NAME
00883 << " WHERE char_id = " << CharId
00884 << " AND skill_id = " << SkillId;
00885 mDb->execSql(sql.str());
00886 return;
00887 }
00888
00889
00890 std::ostringstream sql;
00891 sql << "UPDATE " << CHAR_SKILLS_TBL_NAME
00892 << " SET skill_exp = " << SkillValue
00893 << " WHERE char_id = " << CharId
00894 << " AND skill_id = " << SkillId;
00895 mDb->execSql(sql.str());
00896
00897
00898 if (mDb->getModifiedRows() > 0)
00899 {
00900 return;
00901 }
00902
00903 sql.clear();
00904 sql.str("");
00905 sql << "INSERT INTO " << CHAR_SKILLS_TBL_NAME << " "
00906 << "(char_id, skill_id, skill_exp) VALUES ( "
00907 << CharId << ", "
00908 << SkillId << ", "
00909 << SkillValue << ")";
00910 mDb->execSql(sql.str());
00911 }
00912 catch (const dal::DbSqlQueryExecFailure &e)
00913 {
00914 LOG_ERROR("DALStorage::updateExperience: " << e.what());
00915 throw;
00916 }
00917 }
00918
00919
00920
00924 void DALStorage::addGuild(Guild* guild)
00925 {
00926 std::ostringstream insertSql;
00927 insertSql << "insert into " << GUILDS_TBL_NAME
00928 << " (name) "
00929 << " values (\""
00930 << guild->getName() << "\");";
00931 mDb->execSql(insertSql.str());
00932
00933 std::ostringstream selectSql;
00934 selectSql << "select id from " << GUILDS_TBL_NAME
00935 << " where name = \"" << guild->getName() << "\";";
00936 const dal::RecordSet& guildInfo = mDb->execSql(selectSql.str());
00937 string_to<unsigned int> toUint;
00938 unsigned id = toUint(guildInfo(0, 0));
00939 guild->setId(id);
00940 }
00941
00945 void DALStorage::removeGuild(Guild* guild)
00946 {
00947 std::ostringstream sql;
00948 sql << "delete from " << GUILDS_TBL_NAME
00949 << " where id = '"
00950 << guild->getId() << "';";
00951 mDb->execSql(sql.str());
00952 }
00953
00957 void DALStorage::addGuildMember(int guildId, int memberId)
00958 {
00959 std::ostringstream sql;
00960
00961 try
00962 {
00963 sql << "insert into " << GUILD_MEMBERS_TBL_NAME
00964 << " (guild_id, member_id, rights)"
00965 << " values ("
00966 << guildId << ", \""
00967 << memberId << "\", "
00968 << 0 << ");";
00969 mDb->execSql(sql.str());
00970 }
00971 catch (const dal::DbSqlQueryExecFailure& e) {
00972
00973 LOG_ERROR("SQL query failure: " << e.what());
00974 }
00975 }
00976
00980 void DALStorage::removeGuildMember(int guildId, int memberId)
00981 {
00982 std::ostringstream sql;
00983
00984 try
00985 {
00986 sql << "delete from " << GUILD_MEMBERS_TBL_NAME
00987 << " where member_id = \""
00988 << memberId << "\" and guild_id = '"
00989 << guildId << "';";
00990 mDb->execSql(sql.str());
00991 }
00992 catch (const dal::DbSqlQueryExecFailure& e)
00993 {
00994
00995 LOG_ERROR("SQL query failure: " << e.what());
00996 }
00997 }
00998
00999 void DALStorage::setMemberRights(int guildId, int memberId, int rights)
01000 {
01001 std::ostringstream sql;
01002
01003 try
01004 {
01005 sql << "update " << GUILD_MEMBERS_TBL_NAME
01006 << " set rights = '" << rights << "'"
01007 << " where member_id = \""
01008 << memberId << "\";";
01009 mDb->execSql(sql.str());
01010 }
01011 catch (const dal::DbSqlQueryExecFailure& e)
01012 {
01013
01014 LOG_ERROR("SQL query failure: " << e.what());
01015 }
01016 }
01017
01021 std::list<Guild*> DALStorage::getGuildList()
01022 {
01023 std::list<Guild*> guilds;
01024 std::stringstream sql;
01025 string_to<short> toShort;
01026
01031 try
01032 {
01033 sql << "select id, name from " << GUILDS_TBL_NAME << ";";
01034 const dal::RecordSet& guildInfo = mDb->execSql(sql.str());
01035
01036
01037 if(guildInfo.isEmpty())
01038 {
01039 return guilds;
01040 }
01041
01042
01043 for ( unsigned int i = 0; i < guildInfo.rows(); ++i)
01044 {
01045 Guild* guild = new Guild(guildInfo(i,1));
01046 guild->setId(toShort(guildInfo(i,0)));
01047 guilds.push_back(guild);
01048 }
01049 string_to< unsigned > toUint;
01050
01054 for (std::list<Guild*>::iterator itr = guilds.begin();
01055 itr != guilds.end();
01056 ++itr)
01057 {
01058 std::ostringstream memberSql;
01059 memberSql << "select member_id, rights from " << GUILD_MEMBERS_TBL_NAME
01060 << " where guild_id = '" << (*itr)->getId() << "';";
01061 const dal::RecordSet& memberInfo = mDb->execSql(memberSql.str());
01062
01063 std::list<std::pair<int, int> > members;
01064 for (unsigned int j = 0; j < memberInfo.rows(); ++j)
01065 {
01066 members.push_back(std::pair<int, int>(toUint(memberInfo(j, 0)), toUint(memberInfo(j, 1))));
01067 }
01068
01069 for (std::list<std::pair<int, int> >::const_iterator i = members.begin();
01070 i != members.end();
01071 ++i)
01072 {
01073 Character *character = getCharacter((*i).first, NULL);
01074 if (character)
01075 {
01076 character->addGuild((*itr)->getName());
01077 (*itr)->addMember(character->getDatabaseID(), (*i).second);
01078 }
01079 }
01080 }
01081 }
01082 catch (const dal::DbSqlQueryExecFailure& e) {
01083
01084 LOG_ERROR("SQL query failure: " << e.what());
01085 }
01086
01087 return guilds;
01088 }
01089
01090 std::string DALStorage::getQuestVar(int id, const std::string &name)
01091 {
01092 try
01093 {
01094 std::ostringstream query;
01095 query << "select value from " << QUESTS_TBL_NAME
01096 << " where owner_id = '" << id << "' and name = '"
01097 << name << "';";
01098 const dal::RecordSet &info = mDb->execSql(query.str());
01099
01100 if (!info.isEmpty()) return info(0, 0);
01101 }
01102 catch (const dal::DbSqlQueryExecFailure &e)
01103 {
01104 LOG_ERROR("(DALStorage::getQuestVar) SQL query failure: " << e.what());
01105 }
01106
01107 return std::string();
01108 }
01109
01110 std::string DALStorage::getWorldStateVar(const std::string &name, int map_id)
01111 {
01112 try
01113 {
01114 std::ostringstream query;
01115 query << "SELECT value "
01116 << " FROM " << WORLD_STATES_TBL_NAME
01117 << " WHERE state_name = '" << name << "'";
01118
01119
01120 if (map_id >= 0)
01121 {
01122 query << " AND map_id = '" << map_id << "'";
01123 }
01124
01125 query << ";";
01126 const dal::RecordSet &info = mDb->execSql(query.str());
01127
01128 if (!info.isEmpty()) return info(0, 0);
01129 }
01130 catch (const dal::DbSqlQueryExecFailure &e)
01131 {
01132 LOG_ERROR("(DALStorage::getWorldStateVar) SQL query failure: " << e.what());
01133 }
01134
01135 return std::string();
01136 }
01137
01138 void DALStorage::setWorldStateVar(const std::string &name, const std::string &value)
01139 {
01140 return setWorldStateVar(name, -1, value);
01141 }
01142
01143 void DALStorage::setWorldStateVar(const std::string &name,
01144 int map_id,
01145 const std::string &value)
01146 {
01147 try
01148 {
01149
01150 if (value.empty())
01151 {
01152 std::ostringstream deleteStateVar;
01153 deleteStateVar << "DELETE FROM " << WORLD_STATES_TBL_NAME
01154 << " WHERE state_name = '" << name << "'";
01155 if (map_id >= 0)
01156 {
01157 deleteStateVar << " AND map_id = '" << map_id << "'";
01158 }
01159 deleteStateVar << ";";
01160 mDb->execSql(deleteStateVar.str());
01161 return;
01162 }
01163
01164
01165 std::ostringstream updateStateVar;
01166 updateStateVar << "UPDATE " << WORLD_STATES_TBL_NAME
01167 << " SET value = '" << value << "', "
01168 << " moddate = '" << time(NULL) << "' "
01169 << " WHERE state_name = '" << name << "'";
01170
01171 if (map_id >= 0)
01172 {
01173 updateStateVar << " AND map_id = '" << map_id << "'";
01174 }
01175 updateStateVar << ";";
01176 mDb->execSql(updateStateVar.str());
01177
01178
01179 if (mDb->getModifiedRows() >= 1)
01180 {
01181 return;
01182 }
01183
01184
01185 std::ostringstream insertStateVar;
01186 insertStateVar << "INSERT INTO " << WORLD_STATES_TBL_NAME
01187 << " (state_name, map_id, value , moddate) VALUES ("
01188 << "'" << name << "', ";
01189 if (map_id >= 0)
01190 {
01191 insertStateVar << "'" << map_id << "', ";
01192 }
01193 else
01194 {
01195 insertStateVar << "NULL , ";
01196 }
01197 insertStateVar << "'" << value << "', "
01198 << "'" << time(NULL) << "');";
01199 mDb->execSql(insertStateVar.str());
01200 }
01201 catch (const dal::DbSqlQueryExecFailure &e)
01202 {
01203 LOG_ERROR("(DALStorage::setWorldStateVar) SQL query failure: " << e.what());
01204 }
01205 }
01206
01207 void DALStorage::setQuestVar(int id, const std::string &name,
01208 const std::string &value)
01209 {
01210 try
01211 {
01212 std::ostringstream query1;
01213 query1 << "delete from " << QUESTS_TBL_NAME
01214 << " where owner_id = '" << id << "' and name = '"
01215 << name << "';";
01216 mDb->execSql(query1.str());
01217
01218 if (value.empty()) return;
01219
01220 std::ostringstream query2;
01221 query2 << "insert into " << QUESTS_TBL_NAME
01222 << " (owner_id, name, value) values ('"
01223 << id << "', '" << name << "', '" << value << "');";
01224 mDb->execSql(query2.str());
01225 }
01226 catch (const dal::DbSqlQueryExecFailure &e)
01227 {
01228 LOG_ERROR("(DALStorage::setQuestVar) SQL query failure: " << e.what());
01229 }
01230 }
01231
01232 void DALStorage::banCharacter(int id, int duration)
01233 {
01234 try
01235 {
01236 std::ostringstream query;
01237 query << "select user_id from " << CHARACTERS_TBL_NAME
01238 << " where id = '" << id << "';";
01239 const dal::RecordSet &info = mDb->execSql(query.str());
01240 if (info.isEmpty())
01241 {
01242 LOG_ERROR("Tried to ban an unknown user.");
01243 return;
01244 }
01245
01246 std::ostringstream sql;
01247 sql << "update " << ACCOUNTS_TBL_NAME
01248 << " set level = '" << AL_BANNED << "', banned = '"
01249 << time(NULL) + duration * 60
01250 << "' where id = '" << info(0, 0) << "';";
01251 mDb->execSql(sql.str());
01252 }
01253 catch (const dal::DbSqlQueryExecFailure &e)
01254 {
01255 LOG_ERROR("(DALStorage::banAccount) SQL query failure: " << e.what());
01256 }
01257 }
01258
01259 void DALStorage::delCharacter(int charId, bool startTransaction = true) const
01260 {
01261 if (startTransaction)
01262 mDb->beginTransaction();
01263 try
01264 {
01265 std::ostringstream sql;
01266
01267
01268 sql << "DELETE FROM " << INVENTORIES_TBL_NAME
01269 << " WHERE owner_id = '" << charId << "';";
01270 mDb->execSql(sql.str());
01271
01272
01273 sql.clear();
01274 sql.str("");
01275 sql << "DELETE FROM " << CHAR_SKILLS_TBL_NAME
01276 << " WHERE char_id = '" << charId << "';";
01277 mDb->execSql(sql.str());
01278
01279
01280 sql.clear();
01281 sql.str("");
01282 sql << "DELETE FROM " << QUESTS_TBL_NAME
01283 << " WHERE owner_id = '" << charId << "';";
01284 mDb->execSql(sql.str());
01285
01286
01287 sql.clear();
01288 sql.str("");
01289 sql << "DELETE FROM " << GUILD_MEMBERS_TBL_NAME
01290 << " WHERE member_id = '" << charId << "';";
01291 mDb->execSql(sql.str());
01292
01293
01294 sql.clear();
01295 sql.str("");
01296 sql << "DELETE FROM " << AUCTION_TBL_NAME
01297 << " WHERE char_id = '" << charId << "';";
01298 mDb->execSql(sql.str());
01299
01300
01301 sql.clear();
01302 sql.str("");
01303 sql << "DELETE FROM " << AUCTION_BIDS_TBL_NAME
01304 << " WHERE char_id = '" << charId << "';";
01305 mDb->execSql(sql.str());
01306
01307
01308 sql.clear();
01309 sql.str("");
01310 sql << "DELETE FROM " << CHARACTERS_TBL_NAME
01311 << " WHERE id = '" << charId << "';";
01312 mDb->execSql(sql.str());
01313
01314 if (startTransaction)
01315 mDb->commitTransaction();
01316 }
01317 catch (const dal::DbSqlQueryExecFailure &e)
01318 {
01319 if (startTransaction)
01320 mDb->rollbackTransaction();
01321 LOG_ERROR("(DALStorage::delCharacter) SQL query failure: " << e.what());
01322 }
01323 }
01324
01325 void DALStorage::delCharacter(Character *character,
01326 bool startTransaction = true) const
01327 {
01328 delCharacter(character->getDatabaseID(), startTransaction);
01329 }
01330
01331 void DALStorage::checkBannedAccounts()
01332 {
01333 try
01334 {
01335
01336 std::ostringstream sql;
01337 sql << "update " << ACCOUNTS_TBL_NAME
01338 << " set level = " << AL_PLAYER << ", banned = 0"
01339 << " where level = " << AL_BANNED
01340 << " AND banned <= " << time(NULL) << ";";
01341 mDb->execSql(sql.str());
01342 }
01343 catch (const dal::DbSqlQueryExecFailure &e)
01344 {
01345 LOG_ERROR("(DALStorage::checkBannedAccounts) SQL query failure: " << e.what());
01346 }
01347 }
01348
01349 void DALStorage::setAccountLevel(int id, int level)
01350 {
01351 try
01352 {
01353 std::ostringstream sql;
01354 sql << "update " << ACCOUNTS_TBL_NAME
01355 << " set level = " << level
01356 << " where id = " << id << ";";
01357 mDb->execSql(sql.str());
01358 }
01359 catch (const dal::DbSqlQueryExecFailure &e)
01360 {
01361 LOG_ERROR("(DALStorage::setAccountLevel) SQL query failure: " << e.what());
01362 }
01363 }
01364
01365 void DALStorage::setPlayerLevel(int id, int level)
01366 {
01367 try
01368 {
01369 std::ostringstream sql;
01370 sql << "update " << CHARACTERS_TBL_NAME
01371 << " set level = " << level
01372 << " where id = " << id << ";";
01373 mDb->execSql(sql.str());
01374 }
01375 catch (const dal::DbSqlQueryExecFailure &e)
01376 {
01377 LOG_ERROR("(DALStorage::setPlayerLevel) SQL query failure: " << e.what());
01378 }
01379 }
01380
01381 void DALStorage::storeLetter(Letter *letter)
01382 {
01383 std::ostringstream sql;
01384 if (letter->getId() == 0)
01385 {
01386
01387 sql << "INSERT INTO " << POST_TBL_NAME << " VALUES ( "
01388 << "NULL, "
01389 << letter->getSender()->getDatabaseID() << ", "
01390 << letter->getReceiver()->getDatabaseID() << ", "
01391 << letter->getExpiry() << ", "
01392 << time(NULL) << ", "
01393 << "'" << letter->getContents() << "' )";
01394
01395 mDb->execSql(sql.str());
01396 letter->setId(mDb->getLastId());
01397
01398
01399
01400 return;
01401 }
01402 else
01403 {
01404
01405 sql << "UPDATE " << POST_TBL_NAME
01406 << " SET sender_id = '" << letter->getSender()->getDatabaseID() << "', "
01407 << " receiver_id = '" << letter->getReceiver()->getDatabaseID() << "', "
01408 << " letter_type = '" << letter->getType() << "', "
01409 << " expiration_date = '" << letter->getExpiry() << "', "
01410 << " sending_date = '" << time(NULL) << "', "
01411 << " letter_text = '" << letter->getContents() << "' "
01412 << " WHERE letter_id = '" << letter->getId() << "'";
01413
01414 mDb->execSql(sql.str());
01415
01416 if (mDb->getModifiedRows() == 0)
01417 {
01418
01419 LOG_ERROR("(DALStorage::storePost) trying to update nonexsistant letter");
01420 throw "(DALStorage::storePost) trying to update nonexsistant letter";
01421 }
01422
01423
01424 }
01425 }
01426
01427 Post* DALStorage::getStoredPost(int playerId)
01428 {
01429 Post* p = new Post();
01430
01431
01432 string_to< unsigned > toUint;
01433
01434 std::ostringstream sql;
01435 sql << "SELECT * FROM " << POST_TBL_NAME
01436 << " WHERE receiver_id = " << playerId;
01437
01438 const dal::RecordSet &post = mDb->execSql(sql.str());
01439
01440 if (post.isEmpty())
01441 {
01442
01443 return p;
01444 }
01445
01446 for (unsigned int i = 0; i < post.rows(); i++ )
01447 {
01448
01449 Character *sender = getCharacter(toUint(post(i, 1)), NULL);
01450 Character *receiver = getCharacter(toUint(post(i, 2)), NULL);
01451
01452 Letter *letter = new Letter(toUint( post(0,3) ), sender, receiver);
01453
01454 letter->setId( toUint(post(0, 0)) );
01455 letter->setExpiry( toUint(post(0, 4)) );
01456 letter->addText( post(0, 6) );
01457
01458
01459
01460
01461 p->addLetter(letter);
01462 }
01463
01464 return p;
01465 }
01466
01467 void DALStorage::deletePost(Letter* letter)
01468 {
01469 mDb->beginTransaction();
01470
01471 try
01472 {
01473 std::ostringstream sql;
01474
01475
01476
01477 sql << "DELETE FROM " << POST_ATTACHMENTS_TBL_NAME
01478 << " WHERE letter_id = " << letter->getId();
01479 mDb->execSql(sql.str());
01480
01481
01482 sql.clear();
01483 sql.str("");
01484 sql << "DELETE FROM " << POST_TBL_NAME
01485 << " WHERE letter_id = " << letter->getId();
01486 mDb->execSql(sql.str());
01487
01488 mDb->commitTransaction();
01489 letter->setId(0);
01490 }
01491 catch(const dal::DbSqlQueryExecFailure &e)
01492 {
01493 mDb->rollbackTransaction();
01494 LOG_ERROR("(DALStorage::deletePost) SQL query failure: " << e.what());
01495 }
01496 }
01497
01498 void DALStorage::SyncDatabase(void)
01499 {
01500 xmlDocPtr doc = xmlReadFile(DEFAULT_ITEM_FILE, NULL, 0);
01501 if (!doc)
01502 {
01503 LOG_ERROR("Item Manager: Error while parsing item database (items.xml)!");
01504 return;
01505 }
01506
01507 xmlNodePtr node = xmlDocGetRootElement(doc);
01508 if (!node || !xmlStrEqual(node->name, BAD_CAST "items"))
01509 {
01510 LOG_ERROR("Item Manager:(items.xml) is not a valid database file!");
01511 xmlFreeDoc(doc);
01512 return;
01513 }
01514
01515 mDb->beginTransaction();
01516 int itmCount = 0;
01517 for (node = node->xmlChildrenNode; node != NULL; node = node->next)
01518 {
01519
01520
01521
01522 if (xmlStrEqual(node->name, BAD_CAST "version"))
01523 {
01524 std::string revision = XML::getProperty(node, "revision", std::string());
01525 mItemDbVersion = atoi(revision.c_str());
01526 LOG_INFO("Loading item database version " << mItemDbVersion);
01527 }
01528
01529 if (!xmlStrEqual(node->name, BAD_CAST "item"))
01530 {
01531 continue;
01532 }
01533
01534 if (xmlStrEqual(node->name, BAD_CAST "item"))
01535 {
01536 int id = XML::getProperty(node, "id", 0);
01537 if (id < 500)
01538 {
01539 continue;
01540 }
01541
01542 int weight = XML::getProperty(node, "weight", 0);
01543 std::string type = XML::getProperty(node, "type", "");
01544 std::string name = XML::getProperty(node, "name", "");
01545 std::string desc = XML::getProperty(node, "description", "");
01546 std::string eff = XML::getProperty(node, "effect", "");
01547 std::string image = XML::getProperty(node, "image", "");
01548 std::string dye("");
01549
01550
01551 size_t pipe = image.find("|");
01552 if (pipe != std::string::npos)
01553 {
01554 dye = image.substr(pipe + 1);
01555 image = image.substr(0, pipe);
01556 }
01557
01558 try
01559 {
01560 std::ostringstream sql;
01561 sql << "UPDATE " << ITEMS_TBL_NAME
01562 << " SET name = '" << mDb->escapeSQL(name) << "', "
01563 << " description = '" << mDb->escapeSQL(desc) << "', "
01564 << " image = '" << image << "', "
01565 << " weight = " << weight << ", "
01566 << " itemtype = '" << type << "', "
01567 << " effect = '" << mDb->escapeSQL(eff) << "', "
01568 << " dyestring = '" << dye << "' "
01569 << " WHERE id = " << id;
01570
01571 mDb->execSql(sql.str());
01572 if (mDb->getModifiedRows() == 0)
01573 {
01574 sql.clear();
01575 sql.str("");
01576 sql << "INSERT INTO " << ITEMS_TBL_NAME
01577 << " VALUES ( " << id << ", '" << name << "', '"
01578 << desc << "', '" << image << "', " << weight << ", '"
01579 << type << "', '" << eff << "', '" << dye << "' )";
01580 mDb->execSql(sql.str());
01581 }
01582 itmCount++;
01583 }
01584 catch (const dal::DbSqlQueryExecFailure &e)
01585 {
01586 LOG_ERROR("(DALStorage::SyncDatabase) SQL query failure: " << e.what());
01587 }
01588 }
01589 }
01590
01591 mDb->commitTransaction();
01592 xmlFreeDoc(doc);
01593 }
01594
01595 void DALStorage::setOnlineStatus(int charId, bool online)
01596 {
01597 try
01598 {
01599 std::ostringstream sql;
01600 if (online)
01601 {
01602
01603
01604 sql << "SELECT COUNT(*) FROM " << ONLINE_USERS_TBL_NAME
01605 << " WHERE char_id = " << charId;
01606 const std::string res = mDb->execSql(sql.str())(0, 0);
01607
01608 if (res != "0")
01609 return;
01610
01611 sql.clear();
01612 sql.str("");
01613 sql << "INSERT INTO " << ONLINE_USERS_TBL_NAME
01614 << " VALUES (" << charId << ", " << time(NULL) << ")";
01615 mDb->execSql(sql.str());
01616 }
01617 else
01618 {
01619 sql << "DELETE FROM " << ONLINE_USERS_TBL_NAME
01620 << " WHERE char_id = " << charId;
01621 mDb->execSql(sql.str());
01622 }
01623
01624
01625 }
01626 catch (const dal::DbSqlQueryExecFailure &e)
01627 {
01628 LOG_ERROR("(DALStorage::setOnlineStatus) SQL query failure: " << e.what());
01629 }
01630 }
01631
01632 void DALStorage::addTransaction(const Transaction &trans)
01633 {
01634 try
01635 {
01636 std::stringstream sql;
01637 sql << "INSERT INTO " << TRANSACTION_TBL_NAME
01638 << " VALUES (NULL, " << trans.mCharacterId << ", " << trans.mAction
01639 << ", '" << trans.mMessage << "', " << time(NULL) << ")";
01640 mDb->execSql(sql.str());
01641 }
01642 catch (const dal::DbSqlQueryExecFailure &e)
01643 {
01644 LOG_ERROR("(DALStorage::addTransaction) SQL query failure: " << e.what());
01645 }
01646 }
01647
01648 std::vector<Transaction> DALStorage::getTransactions(unsigned int num)
01649 {
01650 std::vector<Transaction> transactions;
01651 string_to<unsigned int> toUint;
01652
01653 try
01654 {
01655 std::stringstream sql;
01656 sql << "SELECT * FROM " << TRANSACTION_TBL_NAME;
01657 const dal::RecordSet &rec = mDb->execSql(sql.str());
01658
01659 int size = rec.rows();
01660 int start = size - num;
01661
01662 for (int i = start; i < size; ++i)
01663 {
01664 Transaction trans;
01665 trans.mCharacterId = toUint(rec(i, 1));
01666 trans.mAction = toUint(rec(i, 2));
01667 trans.mMessage = rec(i, 3);
01668 transactions.push_back(trans);
01669 }
01670 }
01671 catch (const dal::DbSqlQueryExecFailure &e)
01672 {
01673 LOG_ERROR("(DALStorage::getTransactions) SQL query failure: " << e.what());
01674 }
01675
01676 return transactions;
01677 }
01678
01679 std::vector<Transaction> DALStorage::getTransactions(time_t date)
01680 {
01681 std::vector<Transaction> transactions;
01682 string_to<unsigned int> toUint;
01683
01684 try
01685 {
01686 std::stringstream sql;
01687 sql << "SELECT * FROM " << TRANSACTION_TBL_NAME << " WHERE time > "
01688 << date;
01689 const dal::RecordSet &rec = mDb->execSql(sql.str());
01690
01691 for (unsigned int i = 0; i < rec.rows(); ++i)
01692 {
01693 Transaction trans;
01694 trans.mCharacterId = toUint(rec(i, 1));
01695 trans.mAction = toUint(rec(i, 2));
01696 trans.mMessage = rec(i, 3);
01697 transactions.push_back(trans);
01698 }
01699 }
01700 catch (const dal::DbSqlQueryExecFailure &e)
01701 {
01702 LOG_ERROR("(DALStorage::getTransactions) SQL query failure: " << e.what());
01703 }
01704
01705 return transactions;
01706 }