00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "mysqldataprovider.h"
00022
00023 #include "dalexcept.h"
00024
00025 namespace dal
00026 {
00027
00028
00029 const std::string MySqlDataProvider::CFGPARAM_MYSQL_HOST ="mysql_hostname";
00030 const std::string MySqlDataProvider::CFGPARAM_MYSQL_PORT ="mysql_port";
00031 const std::string MySqlDataProvider::CFGPARAM_MYSQL_DB ="mysql_database";
00032 const std::string MySqlDataProvider::CFGPARAM_MYSQL_USER ="mysql_username";
00033 const std::string MySqlDataProvider::CFGPARAM_MYSQL_PWD ="mysql_password";
00034
00035 const std::string MySqlDataProvider::CFGPARAM_MYSQL_HOST_DEF = "localhost";
00036 const unsigned int MySqlDataProvider::CFGPARAM_MYSQL_PORT_DEF = 3306;
00037 const std::string MySqlDataProvider::CFGPARAM_MYSQL_DB_DEF = "tmw";
00038 const std::string MySqlDataProvider::CFGPARAM_MYSQL_USER_DEF = "tmw";
00039 const std::string MySqlDataProvider::CFGPARAM_MYSQL_PWD_DEF = "tmw";
00040
00044 MySqlDataProvider::MySqlDataProvider(void)
00045 throw()
00046 : mDb(0)
00047 {
00048
00049 }
00050
00051
00055 MySqlDataProvider::~MySqlDataProvider(void)
00056 throw()
00057 {
00058
00059
00060
00061
00062
00063 if (mIsConnected) {
00064 disconnect();
00065 }
00066 }
00067
00068
00072 DbBackends
00073 MySqlDataProvider::getDbBackend(void) const
00074 throw()
00075 {
00076 return DB_BKEND_MYSQL;
00077 }
00078
00079
00083 void
00084 MySqlDataProvider::connect()
00085 {
00086 if (mIsConnected) {
00087 return;
00088 }
00089
00090
00091 const std::string hostname
00092 = Configuration::getValue(CFGPARAM_MYSQL_HOST, CFGPARAM_MYSQL_HOST_DEF);
00093 const std::string dbName
00094 = Configuration::getValue(CFGPARAM_MYSQL_DB, CFGPARAM_MYSQL_DB_DEF);
00095 const std::string username
00096 = Configuration::getValue(CFGPARAM_MYSQL_USER, CFGPARAM_MYSQL_USER_DEF);
00097 const std::string password
00098 = Configuration::getValue(CFGPARAM_MYSQL_PWD, CFGPARAM_MYSQL_PWD_DEF);
00099 const unsigned int tcpPort
00100 = Configuration::getValue(CFGPARAM_MYSQL_PORT, CFGPARAM_MYSQL_PORT_DEF);
00101
00102
00103
00104 mDb = mysql_init(NULL);
00105
00106 if (!mDb) {
00107 throw DbConnectionFailure(
00108 "unable to initialize the MySQL library: no memory");
00109 }
00110
00111 LOG_INFO("Trying to connect with mySQL database server '"
00112 << hostname << ":" << tcpPort << "' using '" << username
00113 << "' as user, and '" << dbName << "' as database.");
00114
00115
00116 if (!mysql_real_connect(mDb,
00117 hostname.c_str(),
00118 username.c_str(),
00119 password.c_str(),
00120 dbName.c_str(),
00121 tcpPort,
00122 NULL,
00123 0))
00124 {
00125 std::string msg(mysql_error(mDb));
00126 mysql_close(mDb);
00127
00128 throw DbConnectionFailure(msg);
00129 }
00130
00131
00132 mDbName = dbName;
00133
00134 mIsConnected = true;
00135 LOG_INFO("Connection to mySQL was sucessfull.");
00136 }
00137
00138
00142 const RecordSet&
00143 MySqlDataProvider::execSql(const std::string& sql,
00144 const bool refresh)
00145 {
00146 if (!mIsConnected) {
00147 throw std::runtime_error("not connected to database");
00148 }
00149
00150 LOG_DEBUG("Performing SQL query: "<<sql);
00151
00152
00153
00154
00155 if (refresh || (sql != mSql)) {
00156 mRecordSet.clear();
00157
00158
00159 if (mysql_query(mDb, sql.c_str()) != 0) {
00160 throw DbSqlQueryExecFailure(mysql_error(mDb));
00161 }
00162
00163 if (mysql_field_count(mDb) > 0) {
00164 MYSQL_RES* res;
00165
00166
00167 if (!(res = mysql_store_result(mDb))) {
00168 throw DbSqlQueryExecFailure(mysql_error(mDb));
00169 }
00170
00171
00172 unsigned int nFields = mysql_num_fields(res);
00173 MYSQL_FIELD* fields = mysql_fetch_fields(res);
00174 Row fieldNames;
00175 for (unsigned int i = 0; i < nFields; ++i) {
00176 fieldNames.push_back(fields[i].name);
00177 }
00178 mRecordSet.setColumnHeaders(fieldNames);
00179
00180
00181 MYSQL_ROW row;
00182 while ((row = mysql_fetch_row(res))) {
00183 Row r;
00184
00185 for (unsigned int i = 0; i < nFields; ++i) {
00186 r.push_back(static_cast<char *>(row[i]));
00187 }
00188
00189 mRecordSet.add(r);
00190 }
00191
00192
00193 mysql_free_result(res);
00194 }
00195 }
00196
00197 return mRecordSet;
00198 }
00199
00200
00204 void
00205 MySqlDataProvider::disconnect(void)
00206 {
00207 if (!mIsConnected) {
00208 return;
00209 }
00210
00211
00212
00213 mysql_close(mDb);
00214
00215
00216 mysql_library_end();
00217
00218 mDb = 0;
00219 mIsConnected = false;
00220 }
00221
00222 void
00223 MySqlDataProvider::beginTransaction(void)
00224 throw (std::runtime_error)
00225 {
00226 if (!mIsConnected)
00227 {
00228 const std::string error = "Trying to begin a transaction while not "
00229 "connected to the database!";
00230 LOG_ERROR(error);
00231 throw std::runtime_error(error);
00232 }
00233
00234 mysql_autocommit(mDb, AUTOCOMMIT_OFF);
00235 execSql("BEGIN");
00236 LOG_DEBUG("SQL: started transaction");
00237 }
00238
00239 void
00240 MySqlDataProvider::commitTransaction(void)
00241 throw (std::runtime_error)
00242 {
00243 if (!mIsConnected)
00244 {
00245 const std::string error = "Trying to commit a transaction while not "
00246 "connected to the database!";
00247 LOG_ERROR(error);
00248 throw std::runtime_error(error);
00249 }
00250
00251 if (mysql_commit(mDb) != 0)
00252 {
00253 LOG_ERROR("MySqlDataProvider::commitTransaction: " << mysql_error(mDb));
00254 throw DbSqlQueryExecFailure(mysql_error(mDb));
00255 }
00256 mysql_autocommit(mDb, AUTOCOMMIT_ON);
00257 LOG_DEBUG("SQL: commited transaction");
00258 }
00259
00260 void
00261 MySqlDataProvider::rollbackTransaction(void)
00262 throw (std::runtime_error)
00263 {
00264 if (!mIsConnected)
00265 {
00266 const std::string error = "Trying to rollback a transaction while not "
00267 "connected to the database!";
00268 LOG_ERROR(error);
00269 throw std::runtime_error(error);
00270 }
00271
00272 if (mysql_rollback(mDb) != 0)
00273 {
00274 LOG_ERROR("MySqlDataProvider::rollbackTransaction: " << mysql_error(mDb));
00275 throw DbSqlQueryExecFailure(mysql_error(mDb));
00276 }
00277 mysql_autocommit(mDb, AUTOCOMMIT_ON);
00278 LOG_DEBUG("SQL: transaction rolled back");
00279 }
00280
00281 const unsigned int
00282 MySqlDataProvider::getModifiedRows(void) const
00283 {
00284 if (!mIsConnected)
00285 {
00286 const std::string error = "Trying to getModifiedRows while not "
00287 "connected to the database!";
00288 LOG_ERROR(error);
00289 throw std::runtime_error(error);
00290 }
00291
00292
00293 const my_ulonglong affected = mysql_affected_rows(mDb);
00294
00295 if (affected > INT_MAX)
00296 throw std::runtime_error("MySqlDataProvider::getLastId exceeded INT_MAX");
00297
00298 if (affected == (my_ulonglong)-1)
00299 {
00300 LOG_ERROR("MySqlDataProvider::getModifiedRows: " << mysql_error(mDb));
00301 throw DbSqlQueryExecFailure(mysql_error(mDb));
00302 }
00303
00304 return (unsigned int)affected;
00305 }
00306
00307 const unsigned int
00308 MySqlDataProvider::getLastId(void) const
00309 {
00310 if (!mIsConnected)
00311 {
00312 const std::string error = "not connected to the database!";
00313 LOG_ERROR(error);
00314 throw std::runtime_error(error);
00315 }
00316
00317
00318 const my_ulonglong lastId = mysql_insert_id(mDb);
00319 if (lastId > UINT_MAX)
00320 throw std::runtime_error("MySqlDataProvider::getLastId exceeded INT_MAX");
00321
00322 return (unsigned int)lastId;
00323 }
00324
00325
00326 }