00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
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:
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
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
00235
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