• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

src/data/MySqlConnection.cpp

00001 /*
00002  *   This file is part of the Standard Portable Library (SPL).
00003  *
00004  *   SPL is free software: you can redistribute it and/or modify
00005  *   it under the terms of the GNU General Public License as published by
00006  *   the Free Software Foundation, either version 3 of the License, or
00007  *   (at your option) any later version.
00008  *
00009  *   SPL is distributed in the hope that it will be useful,
00010  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *   GNU General Public License for more details.
00013  *
00014  *   You should have received a copy of the GNU General Public License
00015  *   along with SPL.  If not, see <http://www.gnu.org/licenses/>.
00016  */
00017 #include <spl/types.h>
00018 #include <spl/Debug.h>
00019 
00020 #ifdef _WINDOWS
00021 #include <spl/configwin32.h>
00022 #else
00023 #include <spl/autoconf/config.h>
00024 #endif
00025 
00026 #include <spl/data/MySqlConnection.h>
00027 #include <spl/net/Socket.h>
00028 
00029 #if defined(HAVE_MYSQL_H) || defined(HAVE_MYSQL_MYSQL_H)
00030 
00031 #ifdef HAVE_MYSQL_H
00032 #include <mysql.h>
00033 #else
00034 #include <mysql/mysql.h>
00035 #endif
00036 
00037 void MySqlConnection::FillErrorInfo()
00038 {
00039         m_lasterror.code = mysql_errno((MYSQL *)m_mysql);
00040         strcpy(m_lasterror.errstr, mysql_error((MYSQL *)m_mysql));
00041 }
00042 
00043 MySqlConnection::MySqlConnection
00044 (
00045         const String& serverOrIP, 
00046         const String& database, 
00047         const String& uid, 
00048         const String& pw
00049 )
00050 : Connection(serverOrIP, database, uid, pw)
00051 {
00052         if ( NULL == (m_mysql = mysql_init( NULL )) )
00053         {
00054                 throw OutOfMemoryException();
00055         }
00056         m_lasterror.code = 0;
00057         m_lasterror.errstr[0] = '\0';
00058 }
00059 
00060 MySqlConnection::~MySqlConnection()
00061 {
00062         Close();
00063 }
00064 
00065 void MySqlConnection::Open()
00066 {
00067         if (! mysql_real_connect((MYSQL *)m_mysql, m_host.GetChars(), m_uid.GetChars(), m_pw.GetChars(), m_database.GetChars(), 0, NULL, CLIENT_MULTI_STATEMENTS))
00068         {
00069                 FillErrorInfo();
00070                 mysql_close( (MYSQL *)m_mysql );
00071         }
00072         m_isopen = true;
00073 }
00074 
00075 void MySqlConnection::Close()
00076 {
00077         if ( m_isopen )
00078         {
00079                 mysql_close( (MYSQL *)m_mysql );
00080                 m_isopen = false;
00081         }
00082 }
00083 
00084 void MySqlConnection::ChangeDatabase(const String& db)
00085 {
00086         if (0 != mysql_select_db((MYSQL *)m_mysql, db.GetChars()) )
00087         {
00088                 FillErrorInfo();
00089                 throw new SqlException(m_lasterror.errstr);
00090         }
00091 }
00092 
00093 TransactionPtr MySqlConnection::BeginTransaction()
00094 {
00095         return TransactionPtr();
00096 }
00097 
00098 CommandPtr MySqlConnection::CreateCommand()
00099 {
00100         return MySqlCommandPtr(new MySqlCommand(this));
00101 }
00102 
00103 CommandPtr MySqlConnection::CreateCommand(const String& cmdText)
00104 {
00105         return MySqlCommandPtr(new MySqlCommand(this, cmdText));
00106 }
00107 
00108 RecordSet *_LoadMySqlRecordSet(MYSQL *mysql, MYSQL_RES *result)
00109 {
00110         MYSQL_ROW row;
00111         RecordSet *rs = new RecordSet();
00112         if ( NULL == rs )
00113         {
00114                 mysql_free_result(result);
00115                 mysql_next_result(mysql);
00116                 throw OutOfMemoryException();
00117         }
00118         unsigned int numFields = mysql_num_fields(result);
00119         MYSQL_FIELD *fields = mysql_fetch_fields(result);
00120         for ( unsigned int x = 0; x < numFields; x++ )
00121         {
00122                 switch ( fields[x].type )
00123                 {
00124                 case MYSQL_TYPE_TINY:
00125                         rs->DefineColumn(fields[x].name, DbSqlType::SQL_TYPE_INT8, fields[x].max_length);
00126                         break;
00127                 case MYSQL_TYPE_SHORT:
00128                         rs->DefineColumn(fields[x].name, DbSqlType::SQL_TYPE_INT16, fields[x].max_length);
00129                         break;
00130                 case MYSQL_TYPE_LONG:
00131                         rs->DefineColumn(fields[x].name, DbSqlType::SQL_TYPE_INT32, fields[x].max_length);
00132                         break;
00133                 case MYSQL_TYPE_INT24:
00134                         rs->DefineColumn(fields[x].name, DbSqlType::SQL_TYPE_INT32, fields[x].max_length);
00135                         break;
00136                 case MYSQL_TYPE_LONGLONG:
00137                         rs->DefineColumn(fields[x].name, DbSqlType::SQL_TYPE_INT64, fields[x].max_length);
00138                         break;
00139                 case MYSQL_TYPE_DECIMAL: 
00140                         rs->DefineColumn(fields[x].name, DbSqlType::SQL_TYPE_DECIMAL, fields[x].max_length);
00141                         break;
00142                 case MYSQL_TYPE_NEWDECIMAL:
00143                         rs->DefineColumn(fields[x].name, DbSqlType::SQL_TYPE_DECIMAL, fields[x].max_length);
00144                         break;
00145                 case MYSQL_TYPE_FLOAT:
00146                         rs->DefineColumn(fields[x].name, DbSqlType::SQL_TYPE_FLOAT32, fields[x].max_length);
00147                         break;
00148                 case MYSQL_TYPE_DOUBLE:
00149                         rs->DefineColumn(fields[x].name, DbSqlType::SQL_TYPE_FLOAT64, fields[x].max_length);
00150                         break;
00151                 case MYSQL_TYPE_BIT:
00152                         rs->DefineColumn(fields[x].name, DbSqlType::SQL_TYPE_INT64, fields[x].max_length);
00153                         break;
00154                 case MYSQL_TYPE_TIMESTAMP:
00155                         rs->DefineColumn(fields[x].name, DbSqlType::SQL_TYPE_DATETIME, fields[x].max_length);
00156                         break;
00157                 case MYSQL_TYPE_DATE:
00158                         rs->DefineColumn(fields[x].name, DbSqlType::SQL_TYPE_DATE, fields[x].max_length);
00159                         break;
00160                 case MYSQL_TYPE_TIME:
00161                         mysql_free_result(result);
00162                         mysql_next_result(mysql);
00163                         delete rs;
00164                         throw new NotImplementedException("Time type not implemented");
00165                 case MYSQL_TYPE_DATETIME:
00166                         rs->DefineColumn(fields[x].name, DbSqlType::SQL_TYPE_DATETIME, fields[x].max_length);
00167                         break;
00168                 case MYSQL_TYPE_YEAR:
00169                         mysql_free_result(result);
00170                         mysql_next_result(mysql);
00171                         delete rs;
00172                         throw new NotImplementedException("Year type not implemented");
00173                 case MYSQL_TYPE_STRING:
00174                         rs->DefineColumn(fields[x].name, DbSqlType::SQL_TYPE_CHAR, fields[x].max_length);
00175                         break;
00176                 case MYSQL_TYPE_VAR_STRING:
00177                         rs->DefineColumn(fields[x].name, DbSqlType::SQL_TYPE_VARCHAR, fields[x].max_length);
00178                         break;
00179                 case MYSQL_TYPE_BLOB:   //BLOB or TEXT field (use max_length to determine the maximum length)
00180                         mysql_free_result(result);
00181                         mysql_next_result(mysql);
00182                         delete rs;
00183                         throw new NotImplementedException("BLOB not implemented");
00184                 case MYSQL_TYPE_SET:
00185                         mysql_free_result(result);
00186                         mysql_next_result(mysql);
00187                         delete rs;
00188                         throw new NotImplementedException("SET not implemented");
00189                 case MYSQL_TYPE_ENUM:
00190                         mysql_free_result(result);
00191                         mysql_next_result(mysql);
00192                         delete rs;
00193                         throw new NotImplementedException("ENUM not implemented");
00194                 case MYSQL_TYPE_GEOMETRY:
00195                         mysql_free_result(result);
00196                         mysql_next_result(mysql);
00197                         delete rs;
00198                         throw new NotImplementedException("GEOMENTRY not implemented");
00199                 case MYSQL_TYPE_NULL:
00200                         mysql_free_result(result);
00201                         mysql_next_result(mysql);
00202                         delete rs;
00203                         throw new NotImplementedException("BLOB not implemented");
00204                 default:
00205                         mysql_free_result(result);
00206                         mysql_next_result(mysql);
00207                         delete rs;
00208                         throw new NotImplementedException("Unknown field type");
00209                 }
00210         }
00211 
00212         // do something with the status resultset
00213     while ((row = mysql_fetch_row(result)) != NULL)
00214         {
00215                 unsigned long *lengths = mysql_fetch_lengths(result);
00216                 for ( unsigned int c = 0; c < numFields; c++ )
00217                 {
00218                         rs->GetColumn(c)->AppendParse(row[c], lengths[c]);
00219                 }
00220                 
00221         }
00222         return rs;
00223 }
00224 
00225 RecordSetPtr MySqlConnection::ExecuteQuery(const String& sql)
00226 {
00227         MYSQL_RES *result;
00228 
00229     if ( 0 != mysql_query ((MYSQL *)m_mysql, sql.GetChars()) )
00230         {
00231                 FillErrorInfo();
00232                 throw new SqlException(m_lasterror.errstr);
00233         }
00234         // if this is a stored procedure, two resultsets are returned (at least).
00235         // the first has the call status
00236     if ( NULL == (result = mysql_use_result ((MYSQL *)m_mysql)) )
00237         {
00238                 FillErrorInfo();
00239                 throw new SqlException(m_lasterror.errstr);
00240         }
00241         RecordSetPtr rs = RecordSetPtr(_LoadMySqlRecordSet((MYSQL *)m_mysql, result));
00242         FillErrorInfo();
00243         mysql_free_result(result);
00244         mysql_next_result((MYSQL *)m_mysql);
00245 
00246         return rs;
00247 }
00248 
00249 int MySqlConnection::ExecuteNonQuery(const String& sql)
00250 {
00251         if( 0 != mysql_query((MYSQL *)m_mysql, sql.GetChars()) )
00252         {
00253                 FillErrorInfo();
00254                 throw new SqlException(m_lasterror.errstr);
00255         }
00256         return (int)mysql_affected_rows((MYSQL *)m_mysql);
00257 }
00258 
00259 void MySqlConnection::RegisterThread()
00260 {
00261         mysql_thread_init();
00262 }
00263 
00264 void MySqlConnection::RegisterThreadExit()
00265 {
00266         mysql_thread_end();
00267 }
00268 
00269 void MySqlConnection::AllowOutOfOrderCommandParameters(bool allow)
00270 {
00271         throw new NotImplementedException();
00272 }
00273 
00274 #if defined(DEBUG)
00275 void MySqlConnection::CheckMem() const
00276 {
00277         Connection::CheckMem();
00278 }
00279 
00280 void MySqlConnection::ValidateMem() const
00281 {
00282         Connection::ValidateMem();
00283 }
00284 #endif
00285 
00286 #endif