mysql_db.cpp

Go to the documentation of this file.
00001 /*                                                              
00002  * A database abstraction layer for C++ and ACE framework
00003  * 
00004  * (C) 2006-2007 Thralling Penguin LLC. All rights reserved.
00005  *
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Lesser General Public
00008  * License as published by the Free Software Foundation; either
00009  * version 2.1 of the License, or (at your option) any later version.
00010  *
00011  * This library is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Lesser General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public
00017  * License along with this library; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA                                                                 
00019  */
00020 #define ACE_BUILD_SVC_DLL
00021 #include <fstream>
00022 #include <iomanip>
00023 #include "mysql_db.h"
00024 #include "ace/Log_Msg.h"
00025 #include "ace/svc_export.h"
00026 #include "ace/OS_Memory.h"
00027 #include "ace/OS.h"
00028 #include "mysql/mysql.h"
00029 
00030 namespace DB
00031 {
00032 
00033 MySQL_ResultSet::~MySQL_ResultSet()
00034 {
00035     if (res_) {
00036         ACE_DEBUG((LM_ERROR,"Warning ResultSet wasn't closed or deleted.\n"));
00037     }
00038 }
00039 
00040 bool 
00041 MySQL_ResultSet::close(void)
00042 {
00043     if (!res_) return (false);
00044 
00045     // eat remaining rows, if there are some
00046     while ((row_ = mysql_fetch_row(res_)) != NULL) {
00047         ;
00048     }
00049 
00050     mysql_free_result(res_);
00051     res_ = NULL;
00052     delete this;
00053 
00054     return (true);
00055 }
00056 
00057 bool 
00058 MySQL_ResultSet::next(void)
00059 {
00060     row_ = mysql_fetch_row(res_);
00061     return ((row_ != NULL ? true : false));
00062 }
00063 
00064 unsigned long 
00065 MySQL_ResultSet::recordCount(void) const
00066 {
00067     /* NOTE: This call ALWAYS fails because mysql_use_result
00068        is used, UNTIL all rows have been read. This is documented
00069        in the MySQL manual.
00070 
00071        I still opt for using mysql_use_result as it reduces
00072        the traffic/memory requirements on the client side.
00073     */
00074     return ((unsigned long) mysql_num_rows(res_));
00075 }
00076 
00077 unsigned int 
00078 MySQL_ResultSet::findColumn(const char *fld) const
00079 {
00080     unsigned int num_fields;
00081     unsigned int i;
00082     MYSQL_FIELD *field;
00083 
00084     num_fields = mysql_num_fields(res_);
00085     for (i=0; i<num_fields; i++) {
00086         field = mysql_fetch_field_direct(res_, i);
00087         if (ACE_OS::strcmp(field->name,fld) == 0) {
00088             return (i);
00089         }
00090     }
00091     return (i);
00092 }
00093 
00094 const char *
00095 MySQL_ResultSet::getString(const int idx) const
00096 {
00097     return (row_[idx]);
00098 }
00099 
00100 const int 
00101 MySQL_ResultSet::getInteger(const int idx) const
00102 {
00103     return ((const int) ACE_OS::atoi(row_[idx]));
00104 }
00105 
00106 const bool 
00107 MySQL_ResultSet::getBool(const int idx) const
00108 {
00109     if (row_[idx] && row_[idx][0] == '1') {
00110         return (true);
00111     }
00112     return (false);
00113 }
00114 
00115 const time_t 
00116 MySQL_ResultSet::getUnixTime(const int idx) const
00117 {
00118     struct tm tmp;
00119     // ACE_DEBUG((LM_DEBUG, ACE_TEXT("Read UnixTime: %s\n"), row_[idx]));
00120 
00121     if (row_[idx]) {
00122         // switch on the type of field
00123         // Basically, there are two types of returns I've seen
00124         // 1. has a hypen and is fully parseable
00125         // 2. has no hypen and is an older timestamp field
00126         // The others are raw DATE or TIME
00127         int Ypos = 0;
00128         int Mpos = 4;
00129         int Dpos = 6;
00130         int hpos = 8;
00131         int mpos = 10;
00132         int spos = 12;
00133         if (strchr(row_[idx], '-') != NULL) {
00134             ++Mpos;
00135             Dpos = 8;
00136             hpos = 11;
00137             mpos = 14;
00138             spos = 17;
00139         }
00140         tmp.tm_wday = 0;
00141         tmp.tm_yday = 0;
00142         tmp.tm_isdst = 0;
00143         tmp.tm_year = (((row_[idx][Ypos] - '0') * 1000) + ((row_[idx][Ypos+1] - '0') * 100) + ((row_[idx][Ypos+2] - '0') * 10) + (row_[idx][Ypos+3] - '0')) - 1900;
00144         tmp.tm_mon = (((row_[idx][Mpos] - '0') * 10) + (row_[idx][Mpos+1] - '0')) - 1; /* 0 - 11 */
00145         tmp.tm_mday = (((row_[idx][Dpos] - '0') * 10) + (row_[idx][Dpos+1] - '0')); /* 1 - 31 */
00146         tmp.tm_hour = (((row_[idx][hpos] - '0') * 10) + (row_[idx][hpos+1] - '0')) - 1; /* 0 - 23 */
00147         tmp.tm_min = (((row_[idx][mpos] - '0') * 10) + (row_[idx][mpos+1] - '0')); /* 0-59 */
00148         tmp.tm_sec = (((row_[idx][spos] - '0') * 10) + (row_[idx][spos+1] - '0')); /* 0-59 */
00149 
00150         /*
00151         ACE_DEBUG((LM_DEBUG, ACE_TEXT("y=%d m=%d d=%d h=%d m=%d s=%d\n"), 
00152                    tmp.tm_year,
00153                    tmp.tm_mon,
00154                    tmp.tm_mday,
00155                    tmp.tm_hour,
00156                    tmp.tm_min,
00157                    tmp.tm_sec));
00158         */
00159         return (mktime(&tmp));
00160     }
00161     return (0);
00162 }
00163 
00164 const double 
00165 MySQL_ResultSet::getDouble(const int idx) const
00166 {
00167     char *pEnd;
00168     return ((row_[idx] ? ACE_OS::strtod(row_[idx], &pEnd) : 0));
00169 }
00170 
00171 const float 
00172 MySQL_ResultSet::getFloat(const int idx) const
00173 {
00174     return ((row_[idx] ? atof(row_[idx]) : 0));
00175 }
00176 
00177 const long 
00178 MySQL_ResultSet::getLong(const int idx) const
00179 {
00180     return ((row_[idx] ? atol(row_[idx]) : 0L));
00181 }
00182 
00183 const short 
00184 MySQL_ResultSet::getShort(const int idx) const
00185 {
00186     return ((short) (row_[idx] ? ACE_OS::atoi(row_[idx]) : 0));
00187 }
00188 
00189 void *
00190 MySQL_ResultSet::operator new (size_t bytes)
00191 {
00192   return (::new char[bytes]);
00193 }
00194 #if defined (ACE_HAS_NEW_NOTHROW)
00195 void *
00196 MySQL_ResultSet::operator new (size_t bytes, const ACE_nothrow_t&)
00197 {
00198   return (::new (ACE_nothrow) char[bytes]);
00199 }
00200 #if !defined (ACE_LACKS_PLACEMENT_OPERATOR_DELETE)
00201 void
00202 MySQL_ResultSet::operator delete (void *p, const ACE_nothrow_t&) throw ()
00203 {
00204   delete [] static_cast <char *> (p);
00205 }
00206 #endif /* ACE_LACKS_PLACEMENT_OPERATOR_DELETE */
00207 #endif
00208 void
00209 MySQL_ResultSet::operator delete (void *ptr)
00210 {
00211   delete [] static_cast <char *> (ptr);
00212 }
00213 
00214 bool
00215 MySQL_Connection::open(const char *database, const char *host, const int port, const char *user, const char *pass)
00216 {
00217     if ((mysql_ = mysql_init(NULL)) == NULL) {
00218         return (false);
00219     }
00220     if (mysql_real_connect(
00221             mysql_, 
00222             host, 
00223             user, 
00224             pass, 
00225             NULL, 
00226             (unsigned)port, 
00227             NULL, 
00228             0
00229             ) == NULL) {
00230         return (false);
00231     }
00232     if (mysql_select_db(mysql_, database) != 0) {
00233         return (false);
00234     }
00235     return (true);
00236 }
00237 
00238 bool 
00239 MySQL_Connection::close(void)
00240 {
00241     if (!mysql_) return (false);
00242     mysql_close(mysql_);
00243     mysql_ = NULL;
00244     return (true);
00245 }
00246 
00247 bool
00248 MySQL_Connection::isConnected(void)
00249 {
00250     if (!mysql_) return (false);
00251     return ((mysql_ping(mysql_) == 0 ? true : false));
00252 }
00253 
00254 bool 
00255 MySQL_Connection::execute(const char *sql)
00256 {
00257     if (!mysql_) return (false);
00258     if (mysql_query(mysql_, sql) == 0) {
00259         return (true);
00260     }
00261     return (false);
00262 }
00263 
00264 DB::ResultSet * 
00265 MySQL_Connection::executeQuery(const char *sql)
00266 {
00267     if (!mysql_) return (false);
00268 
00269     if (mysql_query(mysql_, sql)) {
00270         return (0);
00271     }
00272     MYSQL_RES *res = mysql_use_result(mysql_);
00273     if (!res) {
00274         return (0);
00275     }
00276     DB::ResultSet *c = 0;
00277     ACE_NEW_RETURN (c, DB::MySQL_ResultSet(res), 0);
00278     return (c);
00279 }
00280 
00281 char *
00282 MySQL_Connection::escape(const char *str)
00283 {
00284     unsigned long len = strlen(str);
00285     char *buf = new char[len*2+4];
00286     buf[0] = '\'';
00287     len = mysql_escape_string(buf+1, str, len);
00288     buf[++len] = '\'';
00289     buf[++len] = 0;
00290     return (buf);
00291 }
00292 
00293 const char *
00294 MySQL_Connection::unixtimeToSql(const time_t val)
00295 {
00296     char *buf = new char[22];
00297     struct tm *tmp = new struct tm;
00298     buf[0] = '\'';
00299     ACE_OS::strftime(buf+1, 20, "%Y-%m-%d %H:%M:%S", ACE_OS::localtime_r(&val, tmp));
00300     buf[20] = '\'';
00301     buf[21] = 0;
00302     delete tmp;
00303     return (buf);
00304 }
00305 
00306 const unsigned long 
00307 MySQL_Connection::insertId(void)
00308 {
00309     return ((const unsigned long) mysql_insert_id(mysql_));
00310 }
00311 
00312 bool 
00313 MySQL_Connection::beginTrans(void)
00314 {
00315     if (!mysql_) return (false);
00316     if (mysql_query(mysql_, "SET AUTOCOMMIT = 0") != 0) {
00317         return (false);
00318     }
00319     if (mysql_query(mysql_, "BEGIN") == 0) {
00320         return (true);
00321     }
00322     return (false);
00323 }
00324 
00325 bool
00326 MySQL_Connection::commitTrans(void)
00327 {
00328     if (!mysql_) return (false);
00329     if (mysql_query(mysql_, "COMMIT") == 0) {
00330         return (true);
00331     }
00332     return (false);
00333 }
00334 
00335 bool
00336 MySQL_Connection::rollbackTrans(void)
00337 {
00338     if (!mysql_) return (false);
00339     if (mysql_query(mysql_, "ROLLBACK") == 0) {
00340         return (true);
00341     }
00342     return (false);
00343 }
00344 
00345 bool 
00346 MySQL_Connection::setTransactionMode(const enum TRANS_MODE mode)
00347 {
00348     const char *sql = "";
00349 
00350     switch (mode) {
00351     case READ_UNCOMMITTED:
00352         sql = "SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED";
00353         break;
00354     case READ_COMMITTED:
00355         sql = "SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED";
00356         break;
00357     case REPEATABLE_READ:
00358         sql = "SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ";
00359         break;
00360     case SERIALIZABLE:
00361         sql = "SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE";
00362         break;
00363     default:
00364         return false;
00365     }
00366     return (execute(sql));
00367 }
00368 
00369 unsigned int 
00370 MySQL_Connection::errorno(void) const
00371 {
00372     return (mysql_errno(mysql_));
00373 }
00374 
00375 const char *
00376 MySQL_Connection::errormsg(void) const
00377 {
00378     return (mysql_error(mysql_));
00379 }
00380 
00381 const char *
00382 MySQL_Connection::version(void) const
00383 {
00384     static char ret[256];
00385     ACE_OS::snprintf(ret, 256, "MySQL Driver v0.1 using MySQL client library v%s", mysql_get_client_info());
00386     return ((const char *) ret);
00387 }
00388 
00389 void *
00390 MySQL_Connection::operator new (size_t bytes)
00391 {
00392   return (::new char[bytes]);
00393 }
00394 #if defined (ACE_HAS_NEW_NOTHROW)
00395 void *
00396 MySQL_Connection::operator new (size_t bytes, const ACE_nothrow_t&)
00397 {
00398   return (::new (ACE_nothrow) char[bytes]);
00399 }
00400 #if !defined (ACE_LACKS_PLACEMENT_OPERATOR_DELETE)
00401 void
00402 MySQL_Connection::operator delete (void *p, const ACE_nothrow_t&) throw ()
00403 {
00404   delete [] static_cast <char *> (p);
00405 }
00406 #endif /* ACE_LACKS_PLACEMENT_OPERATOR_DELETE */
00407 #endif
00408 void
00409 MySQL_Connection::operator delete (void *ptr)
00410 {
00411   delete [] static_cast <char *> (ptr);
00412 }
00413 
00414 // Returns the Newsweek class pointer.
00415 // The ACE_BUILD_SVC_DLL and ACE_Svc_Export directives are necessary to
00416 // take care of exporting the function for Win32 platforms.
00417 //
00418 
00419 extern "C" ACE_Svc_Export Connection *create_connection (void);
00420 
00421 DB::Connection *
00422 create_connection (void)
00423 {
00424   DB::MySQL_Connection *c = 0;
00425   ACE_NEW_RETURN (c, DB::MySQL_Connection, 0);
00426   return (c);
00427 }
00428 
00429 }
00430 

Generated on Tue Apr 24 18:59:42 2007 for DbAbstract by  doxygen 1.4.7