#include "MysqlWrap.h"
#include "mysqld_error.h"
#include <sstream>
using namespace std;
MysqlReader::MysqlReader()
{
m_pResult = NULL;
m_rowInfo = NULL;
}
MysqlReader::~MysqlReader()
{
Close();
}
string MysqlReader::GetFieldName(int idx, enum_field_types* fieldType)
{
string ret;
if (m_pResult == NULL)
{
return ret;
}
int iMax = mysql_num_fields(m_pResult);
if (idx > -1 && idx < iMax)
{
MYSQL_FIELD* p = mysql_fetch_field_direct(m_pResult, idx);
ret = p->name;
if (fieldType)
{
*fieldType = p->type;
}
}
return ret;
}
int MysqlReader::GetFieldIndex(const string& sFieldName, enum_field_types* fieldType)
{
int ret = -1;
if (m_pResult == NULL)
{
return ret;
}
MYSQL_FIELD* fields = mysql_fetch_fields(m_pResult);
for (size_t i = 0; i < mysql_num_fields(m_pResult); i++)
{
if (sFieldName.compare(fields[i].name) == 0)
{
ret = i;
if (fieldType)
{
*fieldType = fields[i].type;
}
break;
}
}
return ret;
}
int MysqlReader::GetFieldLength(int idx)
{
int ret = -1;
if (m_pResult == NULL)
{
return ret;
}
int iMax = mysql_num_fields(m_pResult);
if (idx > -1 && idx < iMax)
{
unsigned long* array = mysql_fetch_lengths(m_pResult);
ret = array[idx];
}
return ret;
}
int MysqlReader::GetFieldNum()
{
if (m_pResult == NULL)
{
return -1;
}
return mysql_num_fields(m_pResult);
}
int MysqlReader::GetRowNum()
{
if (m_pResult == NULL)
{
return -1;
}
return static_cast<int>(mysql_num_rows(m_pResult));
}
MYSQL_ROW MysqlReader::Read()
{
if (m_pResult == NULL)
{
return NULL;
}
m_rowInfo = mysql_fetch_row(m_pResult);
return m_rowInfo;
}
MYSQL_ROW MysqlReader::FetchRow(int rowPos)
{
if (m_pResult == NULL)
{
return NULL;
}
mysql_data_seek(m_pResult, rowPos);
m_rowInfo = mysql_fetch_row(m_pResult);
return m_rowInfo;
}
void MysqlReader::SetResult(MYSQL_RES* result)
{
m_pResult = result;
}
int MysqlReader::GetInt32(const string& sFieldName)
{
int ret = 0;
if (m_rowInfo)
{
enum_field_types fieldType;
int idx = GetFieldIndex(sFieldName, &fieldType);
if (idx > -1)
{
switch (fieldType)
{
case MYSQL_TYPE_TINY:
case MYSQL_TYPE_SHORT:
case MYSQL_TYPE_LONG:
case MYSQL_TYPE_INT24:
istringstream iss(m_rowInfo[idx]);
iss >> ret;
break;
}
}
}
return ret;
}
int64_t MysqlReader::GetInt64(const string& sFieldName)
{
int64_t ret = 0;
if (m_rowInfo)
{
enum_field_types fieldType;
int idx = GetFieldIndex(sFieldName, &fieldType);
if (idx > -1)
{
switch (fieldType)
{
case MYSQL_TYPE_LONGLONG:
istringstream iss(m_rowInfo[idx]);
iss >> ret;
break;
}
}
}
return ret;
}
string MysqlReader::GetString(const string& sFieldName)
{
string ret;
if (m_rowInfo)
{
enum_field_types fieldType;
int idx = GetFieldIndex(sFieldName, &fieldType);
if (idx > -1)
{
switch (fieldType)
{
case MYSQL_TYPE_TIMESTAMP:
case MYSQL_TYPE_DATETIME:
case MYSQL_TYPE_VARCHAR:
case MYSQL_TYPE_VAR_STRING:
case MYSQL_TYPE_STRING:
ret.assign(m_rowInfo[idx], GetFieldLength(idx));
break;
}
}
}
return ret;
}
void MysqlReader::Close()
{
if (m_pResult)
{
mysql_free_result(m_pResult);
m_pResult = NULL;
}
}
MysqlDB::MysqlDB()
{
memset(&m_mysql, 0x0, sizeof(m_mysql));
mysql_init(&m_mysql);
m_isKeepalive = false;
m_isConnected = false;
m_timeout = 10;
m_encoding = "utf8";
}
MysqlDB::~MysqlDB()
{
Close();
}
bool MysqlDB::Connect(const string& sHost, const string& sUser, const string& sPass, const string& sDBName, int iPort /*= 3306*/, bool isKeepAlive /*= false*/)
{
if (m_isConnected)
{
m_sError = "already connected";
return false;
}
if (m_timeout > 0)
{
int optval = m_timeout;
if (mysql_options(&m_mysql, MYSQL_OPT_CONNECT_TIMEOUT, &optval) != 0)
{
ostringstream oss;
oss << "mysql_options(MYSQL_OPT_CONNECT_TIMEOUT," << optval << ") fail," << mysql_error(&m_mysql);
m_sError = oss.str();
return false;
}
if (mysql_options(&m_mysql, MYSQL_OPT_READ_TIMEOUT, &optval) != 0)
{
ostringstream oss;
oss << "mysql_options(MYSQL_OPT_READ_TIMEOUT," << optval << ") fail," << mysql_error(&m_mysql);
m_sError = oss.str();
return false;
}
if (mysql_options(&m_mysql, MYSQL_OPT_WRITE_TIMEOUT, &optval) != 0)
{
ostringstream oss;
oss << "mysql_options(MYSQL_OPT_WRITE_TIMEOUT," << optval << ") fail," << mysql_error(&m_mysql);
m_sError = oss.str();
return false;
}
}
if (!m_encoding.empty())
{
if (mysql_options(&m_mysql, MYSQL_SET_CHARSET_NAME, m_encoding.c_str()) != 0)
{
ostringstream oss;
oss << "mysql_options(MYSQL_SET_CHARSET_NAME," << m_encoding << ") fail," << mysql_error(&m_mysql);
m_sError = oss.str();
return false;
}
}
m_isKeepalive = isKeepAlive;
if (isKeepAlive)
{
my_bool reconnect = 1;
if (mysql_options(&m_mysql, MYSQL_OPT_RECONNECT, &reconnect) != 0)
{
ostringstream oss;
oss << "mysql_options(MYSQL_OPT_RECONNECT," << reconnect << ") fail," << mysql_error(&m_mysql);
m_sError = oss.str();
return false;
}
}
bool isSucc = false;
if (mysql_real_connect(&m_mysql, sHost.c_str(), sUser.c_str(), sPass.c_str(), sDBName.c_str(), iPort, NULL, 0))
{
m_isConnected = true;
isSucc = true;
}
else
{
ostringstream oss;
oss << "mysql_real_connect() fail," << sHost << ":" << iPort << "," << sDBName << ",mysql_errno," << mysql_errno(&m_mysql) << ",mysql_error," << mysql_error(&m_mysql);
m_sError = oss.str();
}
return isSucc;
}
void MysqlDB::Close()
{
mysql_close(&m_mysql);
m_isConnected = false;
}
bool MysqlDB::IsConnected() const
{
return m_isConnected;
}
int MysqlDB::Execute(const string& sql)
{
return Execute(sql, NULL);
}
auto_ptr<MysqlReader> MysqlDB::Query(const string& sql)
{
auto_ptr<MysqlReader> myRes(new MysqlReader);
int ret = Execute(sql, myRes.get());
return myRes;
}
int MysqlDB::Execute(const string& sql, MysqlReader* reader /*= NULL*/)
{
int iErr = mysql_real_query(&m_mysql, sql.c_str(), sql.length());
if (iErr != 0)
{
int mysqlErrno = mysql_errno(&m_mysql);
if (mysqlErrno == ER_DUP_ENTRY)
{
m_sError = "mysql_real_query() fail,ER_DUP_ENTRY";
return -2;
}
else
{
//尝试ping一下,看能不能通
if (m_isKeepalive)
{
iErr = mysql_ping(&m_mysql);
if (iErr != 0)
{
ostringstream oss;
oss << "2 mysql_ping() fail,return," << iErr << ",mysql_errno," << mysql_errno(&m_mysql) << ",mysql_error," << mysql_error(&m_mysql);
Close();
return -1;
}
//自动重连之后,不用重新设置编码
iErr = mysql_real_query(&m_mysql, sql.c_str(), sql.length());
if (iErr != 0)
{
mysqlErrno = mysql_errno(&m_mysql);
if (mysqlErrno == ER_DUP_ENTRY)
{
m_sError = "2 mysql_real_query() fail,ER_DUP_ENTRY";
return -2;
}
else
{
ostringstream oss;
oss << "2 mysql_real_query() fail,return," << iErr << ",mysql_errno," << mysqlErrno << ",mysql_error," << mysql_error(&m_mysql);
m_sError = oss.str();
return -1;
}
}
}
else
{
ostringstream oss;
oss << "mysql_real_query() fail,return," << iErr << "mysql_errno," << mysqlErrno << ",mysql_error," << mysql_error(&m_mysql);
m_sError = oss.str();
return -1;
}
}
}
int ret = static_cast<int>(mysql_affected_rows(&m_mysql));
if (ret < 0 && reader)
{
MYSQL_RES* pResult = mysql_store_result(&m_mysql);
if (pResult)
{
reader->SetResult(pResult);
ret = static_cast<int>(mysql_num_rows(pResult));
}
else
{
ostringstream oss;
oss << "mysql_store_result() fail,mysql_errno," << mysql_errno(&m_mysql) << ",mysql_error," << mysql_err