00001 #include "DatabaseSvc/MysqlInterface.h"
00002
00003 #include <iostream>
00004 #include <mysql.h>
00005 #include <cstring>
00006
00007 using namespace std;
00008
00009 MysqlInterface::MysqlInterface(){}
00010
00011 MysqlInterface::~MysqlInterface(){}
00012
00013 int MysqlInterface::connect()
00014 {
00015 if( m_reuseConnection )
00016 connect(m_dbHost, m_dbUser, m_dbPasswd);
00017 return 0;
00018 }
00019
00020 int MysqlInterface::connect(std::string host, std::string user, std::string passwd)
00021 {
00022 try {
00023 m_conn = new MYSQL;
00024 mysql_init(m_conn);
00025 MYSQL* ret = 0;
00026 int iattempt = 0;
00027 for(iattempt=0;iattempt<3;iattempt++)
00028 {
00029 ret = mysql_real_connect(m_conn, host.c_str(), user.c_str(), passwd.c_str(),m_dbName.c_str(),3306,NULL,0);
00030 if (ret != 0) {
00031 std::cout << "DatabaseSvc: Connected to MySQL database" << std::endl;
00032 break;
00033 }
00034 else {
00035 std::cout << "Couldn't connect to MySQL database. Trying again." << std::endl;
00036 sleep(1);
00037 }
00038 }
00039
00040 if(ret == 0 && iattempt == 2)
00041 throw (char*)mysql_error(m_conn);
00042
00043 } catch ( std::exception &e ) {
00044
00045 cerr << "Error in MySQL session initialization!" << endl;
00046 cerr << "*** std::exception caught:" << endl;
00047 cerr << "*** error message:" << e.what() << endl;
00048 return -1;
00049
00050 } catch (...) { return -1; }
00051
00052 m_isConnected = true;
00053 return 0;
00054 }
00055
00056 int MysqlInterface::select_db(std::string dbname)
00057 {
00058 int ret = mysql_select_db(m_conn, dbname.c_str());
00059 if ( ret != 0 ) {
00060 disconnect();
00061
00062 sleep(5);
00063 ret = connect(m_dbHost, m_dbUser, m_dbPasswd);
00064 if ( ret == 0 ) {
00065 ret = mysql_select_db(m_conn, dbname.c_str());
00066 }
00067 if (ret != 0) {
00068 throw std::exception();
00069 }
00070 }
00071 return 0;
00072 }
00073
00074 int MysqlInterface::query(std::string dbname, std::string sql)
00075 {
00076 if(! m_reuseConnection)
00077 connect(m_dbHost, m_dbUser, m_dbPasswd);
00078
00079 try{
00080
00081 if(m_dbName != dbname)
00082 {
00083 m_dbName = dbname;
00084 select_db(m_dbName);
00085 }
00086
00087 int status = mysql_real_query(m_conn, sql.c_str(), sql.length());
00088 if (status)
00089 {
00090
00091
00092 std::cerr << "MySQL error: MySQL server has gone away"<< std::endl;
00093 disconnect();
00094
00095 sleep(5);
00096 int ret = connect(m_dbHost, m_dbUser, m_dbPasswd);
00097 if (ret == 0) {
00098 std::cout << "Connected to MySQL database " << std::endl;
00099 select_db(m_dbName);
00100 status = mysql_real_query(m_conn, sql.c_str(), sql.length());
00101 }
00102
00103
00104 if(status)
00105 {
00106 cerr << "Query " << sql << " failed: " << mysql_error(m_conn) << endl;
00107 return -1;
00108 }
00109 }
00110 }
00111 catch(...)
00112 {
00113 cerr << "Could not execute query: " << mysql_error(m_conn) << endl;
00114 return -1;
00115 }
00116
00117 if(! m_reuseConnection)
00118 disconnect();
00119
00120 return 0;
00121 }
00122
00123 int MysqlInterface::query(std::string dbname, std::string sql, DatabaseRecordVector& records)
00124 {
00125 if(! m_reuseConnection)
00126 connect(m_dbHost, m_dbUser, m_dbPasswd);
00127
00128 records.clear();
00129
00130 try{
00131
00132 if(m_dbName != dbname)
00133 {
00134 m_dbName = dbname;
00135 select_db(m_dbName);
00136 }
00137
00138 int status = mysql_real_query(m_conn, sql.c_str(), sql.length());
00139 if (status)
00140 {
00141
00142
00143 std::cerr << "MySQL error: MySQL server has gone away"<< std::endl;
00144 disconnect();
00145
00146 sleep(5);
00147 int ret = connect(m_dbHost, m_dbUser, m_dbPasswd);
00148 if (ret == 0) {
00149 std::cout << "Connected to MySQL database " << std::endl;
00150 select_db(m_dbName);
00151 status = mysql_real_query(m_conn, sql.c_str(), sql.length());
00152 }
00153
00154
00155 if(status)
00156 {
00157 cerr << "Query " << sql << " failed: " << mysql_error(m_conn) << endl;
00158 return -1;
00159 }
00160 }
00161
00162 MYSQL_RES* result = mysql_store_result(m_conn);
00163
00164 if(result)
00165 {
00166 int num_fields = mysql_num_fields(result);
00167
00168 if(num_fields>0)
00169 {
00170 MYSQL_FIELD *fields;
00171 fields = mysql_fetch_fields(result);
00172
00173 MYSQL_ROW row;
00174 while ((row = mysql_fetch_row(result)))
00175 {
00176 unsigned long* lengths;
00177 lengths = mysql_fetch_lengths(result);
00178 DatabaseRecord* dbrec = new DatabaseRecord;
00179 int field;
00180 for(field = 0; field<num_fields; field++)
00181 {
00182 if(row[field]!=0)
00183 {
00184 unsigned long field_len = lengths[field];
00185 char* new_record;
00186 if(fields[field].type==FIELD_TYPE_BLOB)
00187 {
00188 new_record = new char[field_len];
00189 memcpy(new_record, row[field], field_len);
00190 }
00191 else
00192 {
00193 new_record = new char[field_len+1];
00194 strcpy(new_record, row[field]);
00195 }
00196
00197 (*dbrec)[fields[field].name]=new_record;
00198 }
00199 else
00200 {
00201 (*dbrec)[fields[field].name]='\0';
00202 }
00203 }
00204 records.push_back(dbrec);
00205 }
00206 }
00207 mysql_free_result(result);
00208 if(! m_reuseConnection)
00209 disconnect();
00210
00211 return records.size();
00212 }
00213 }
00214 catch(...)
00215 {
00216 cerr << "Could not execute query: " << mysql_error(m_conn) << endl;
00217 if(! m_reuseConnection)
00218 disconnect();
00219 return -1;
00220 }
00221
00222 if(! m_reuseConnection)
00223 disconnect();
00224
00225 return 0;
00226 }
00227
00228 int MysqlInterface::disconnect()
00229 {
00230 if (m_conn)
00231 {
00232 mysql_close(m_conn);
00233 delete m_conn;
00234 m_conn = NULL;
00235 }
00236 m_isConnected = false;
00237 return 0;
00238 }