diff options
author | Andreas Habel <mail@exceptionfault.de> | 2008-09-17 11:32:45 +0000 |
---|---|---|
committer | Andreas Habel <mail@exceptionfault.de> | 2008-09-17 11:32:45 +0000 |
commit | a2af298fd993a129b657671a41f20e3975baf0ef (patch) | |
tree | 9e99436db881465af9738a6637ece7ef6b05fe5f /src/dal/mysqldataprovider.cpp | |
parent | fb677eeec95d583b8b1928a907c815c95f8c4594 (diff) | |
download | manaserv-a2af298fd993a129b657671a41f20e3975baf0ef.tar.gz manaserv-a2af298fd993a129b657671a41f20e3975baf0ef.tar.xz manaserv-a2af298fd993a129b657671a41f20e3975baf0ef.zip |
* Added installation scripts to set up database schemas for mysql, sqlite and postgresql. The create table statements have been completely removed out from the c++ source into separate, provider specific sql files. Accountserver will no longer create a sqlite file if none present.
* Added database specific config parameters to configure each provider independent.
* Simplified the connect routine of DALStorage class since every dataprovider is now responsible to retrieve its own parameters.
* Extended abstract dataprovider to support transactions, functionally implemented for SQLite and mySQL.
* Added methods to retrieve last inserted auto-increment value and the number of modified rows by the last statement.
* Rewrite of DALStorage class to be a little more transactional.
* Fixed a bug when deleting a character. Old function left data in quests table and guilds table.
* Doxygen now also includes non-documented functions and provides a dictionary for all classes
Diffstat (limited to 'src/dal/mysqldataprovider.cpp')
-rw-r--r-- | src/dal/mysqldataprovider.cpp | 154 |
1 files changed, 142 insertions, 12 deletions
diff --git a/src/dal/mysqldataprovider.cpp b/src/dal/mysqldataprovider.cpp index 85084dc..f6e422f 100644 --- a/src/dal/mysqldataprovider.cpp +++ b/src/dal/mysqldataprovider.cpp @@ -28,6 +28,18 @@ namespace dal { +const std::string MySqlDataProvider::CFGPARAM_MYSQL_HOST ="mysql_hostname"; +const std::string MySqlDataProvider::CFGPARAM_MYSQL_PORT ="mysql_port"; +const std::string MySqlDataProvider::CFGPARAM_MYSQL_DB ="mysql_database"; +const std::string MySqlDataProvider::CFGPARAM_MYSQL_USER ="mysql_username"; +const std::string MySqlDataProvider::CFGPARAM_MYSQL_PWD ="mysql_password"; + +const std::string MySqlDataProvider::CFGPARAM_MYSQL_HOST_DEF = "localhost"; +const unsigned int MySqlDataProvider::CFGPARAM_MYSQL_PORT_DEF = 3306; +const std::string MySqlDataProvider::CFGPARAM_MYSQL_DB_DEF = "tmw"; +const std::string MySqlDataProvider::CFGPARAM_MYSQL_USER_DEF = "tmw"; +const std::string MySqlDataProvider::CFGPARAM_MYSQL_PWD_DEF = "tmw"; + /** * Constructor. */ @@ -71,14 +83,24 @@ MySqlDataProvider::getDbBackend(void) const * Create a connection to the database. */ void -MySqlDataProvider::connect(const std::string& dbName, - const std::string& userName, - const std::string& password) +MySqlDataProvider::connect() { if (mIsConnected) { return; } + // retrieve configuration from config file + const std::string hostname + = Configuration::getValue(CFGPARAM_MYSQL_HOST, CFGPARAM_MYSQL_HOST_DEF); + const std::string dbName + = Configuration::getValue(CFGPARAM_MYSQL_DB, CFGPARAM_MYSQL_DB_DEF); + const std::string username + = Configuration::getValue(CFGPARAM_MYSQL_USER, CFGPARAM_MYSQL_USER_DEF); + const std::string password + = Configuration::getValue(CFGPARAM_MYSQL_PWD, CFGPARAM_MYSQL_PWD_DEF); + const unsigned int tcpPort + = Configuration::getValue(CFGPARAM_MYSQL_PORT, CFGPARAM_MYSQL_PORT_DEF); + // allocate and initialize a new MySQL object suitable // for mysql_real_connect(). mDb = mysql_init(NULL); @@ -88,17 +110,19 @@ MySqlDataProvider::connect(const std::string& dbName, "unable to initialize the MySQL library: no memory"); } - // insert connection options here. + LOG_INFO("Trying to connect with mySQL database server '" + << hostname << ":" << tcpPort << "' using '" << username + << "' as user, and '" << dbName << "' as database."); // actually establish the connection. - if (!mysql_real_connect(mDb, // handle to the connection - NULL, // localhost - userName.c_str(), // user name - password.c_str(), // user password - dbName.c_str(), // database name - 0, // use default TCP port - NULL, // use defaut socket - 0)) // client flags + if (!mysql_real_connect(mDb, // handle to the connection + hostname.c_str(), // hostname + username.c_str(), // username + password.c_str(), // password + dbName.c_str(), // database name + tcpPort, // tcp port + NULL, // socket, currently not used + 0)) // client flags { std::string msg(mysql_error(mDb)); mysql_close(mDb); @@ -110,6 +134,7 @@ MySqlDataProvider::connect(const std::string& dbName, mDbName = dbName; mIsConnected = true; + LOG_INFO("Connection to mySQL was sucessfull."); } @@ -124,6 +149,8 @@ MySqlDataProvider::execSql(const std::string& sql, throw std::runtime_error("not connected to database"); } + LOG_DEBUG("Performing SQL query: "<<sql); + // do something only if the query is different from the previous // or if the cache must be refreshed // otherwise just return the recordset from cache. @@ -194,5 +221,108 @@ MySqlDataProvider::disconnect(void) mIsConnected = false; } +void +MySqlDataProvider::beginTransaction(void) + throw (std::runtime_error) +{ + if (!mIsConnected) + { + const std::string error = "Trying to begin a transaction while not " + "connected to the database!"; + LOG_ERROR(error); + throw std::runtime_error(error); + } + + mysql_autocommit(mDb, AUTOCOMMIT_OFF); + execSql("BEGIN"); + LOG_DEBUG("SQL: started transaction"); +} + +void +MySqlDataProvider::commitTransaction(void) + throw (std::runtime_error) +{ + if (!mIsConnected) + { + const std::string error = "Trying to commit a transaction while not " + "connected to the database!"; + LOG_ERROR(error); + throw std::runtime_error(error); + } + + if (mysql_commit(mDb) != 0) + { + LOG_ERROR("MySqlDataProvider::commitTransaction: " << mysql_error(mDb)); + throw DbSqlQueryExecFailure(mysql_error(mDb)); + } + mysql_autocommit(mDb, AUTOCOMMIT_ON); + LOG_DEBUG("SQL: commited transaction"); +} + +void +MySqlDataProvider::rollbackTransaction(void) + throw (std::runtime_error) +{ + if (!mIsConnected) + { + const std::string error = "Trying to rollback a transaction while not " + "connected to the database!"; + LOG_ERROR(error); + throw std::runtime_error(error); + } + + if (mysql_rollback(mDb) != 0) + { + LOG_ERROR("MySqlDataProvider::rollbackTransaction: " << mysql_error(mDb)); + throw DbSqlQueryExecFailure(mysql_error(mDb)); + } + mysql_autocommit(mDb, AUTOCOMMIT_ON); + LOG_DEBUG("SQL: transaction rolled back"); +} + +const unsigned int +MySqlDataProvider::getModifiedRows(void) const +{ + if (!mIsConnected) + { + const std::string error = "Trying to getModifiedRows while not " + "connected to the database!"; + LOG_ERROR(error); + throw std::runtime_error(error); + } + + // FIXME: not sure if this is correct to bring 64bit int into int? + const my_ulonglong affected = mysql_affected_rows(mDb); + + if (affected > INT_MAX) + throw std::runtime_error("MySqlDataProvider::getLastId exceeded INT_MAX"); + + if (affected == (my_ulonglong)-1) + { + LOG_ERROR("MySqlDataProvider::getModifiedRows: " << mysql_error(mDb)); + throw DbSqlQueryExecFailure(mysql_error(mDb)); + } + + return (unsigned int)affected; +} + +const unsigned int +MySqlDataProvider::getLastId(void) const +{ + if (!mIsConnected) + { + const std::string error = "not connected to the database!"; + LOG_ERROR(error); + throw std::runtime_error(error); + } + + // FIXME: not sure if this is correct to bring 64bit int into int? + const my_ulonglong lastId = mysql_insert_id(mDb); + if (lastId > UINT_MAX) + throw std::runtime_error("MySqlDataProvider::getLastId exceeded INT_MAX"); + + return (unsigned int)lastId; +} + } // namespace dal |