聊天服务器——mysql

mysql 的api封装

mysql的头文件

#include <unistd.h>
#include <mysql/mysql.h>
#include <mysql/errmsg.h>
#include <stdio.h>
#include <string>
#include <sys/types.h>
#include <errno.h>
#include "base/Logging.h"
#include "QueryResult.h"
#include <iostream>//cout cin cerr
using namespace std;
​
class MySQLTool
{
public:
    MySQLTool();
    ~MySQLTool();
    bool connect(const string& host, const string& user, const string& passwd, const string& db, unsigned port = 3306);
    //用智能指针的好处是,不用再把里面查询的结果复制一次,而是直接返回,因为有时候数据量有点大
    QueryResultPtr Query(const string& sql);
    bool Execute(const string& sql);
    bool Execute(const string& sql, uint32_t& nAffectedCount, int& nErrno);
    const string GetDBName()const { return m_dbname; }
private:
    MYSQL* m_mysql;
    string m_host;
    string m_user;
    string m_passwd;
    string m_dbname;
    unsigned m_port;
};

mysql的cpp文件

#include "mysqltool.h"
extern void mysql_close(MYSQL* sock);
​
MySQLTool::MySQLTool()
{
    m_mysql = NULL;
    m_port = 3306;
}
​
MySQLTool::~MySQLTool()
{
    if (m_mysql != NULL) {
        MYSQL* tmp = m_mysql;
        m_mysql = NULL;
        mysql_close(tmp);
    }
}
​
bool MySQLTool::connect(const string& host, const string& user, const string& passwd, const string& db, unsigned port)
{
    //如果前面有数据库了,先关掉
    if (m_mysql != NULL) {
        MYSQL* tmp = m_mysql;
        m_mysql = NULL;
        mysql_close(tmp);
    }
    //再初始化
    m_mysql = mysql_init(m_mysql);
    //mysql 默认是3306
    m_mysql = mysql_real_connect(m_mysql, host.c_str(), user.c_str(), passwd.c_str(), db.c_str(), port, NULL, 0);
    cout << host << std::endl << user << std::endl << passwd << std::endl << db << std::endl;
​
    if (m_mysql != NULL) {
        m_host = host;
        m_user = user;
        m_passwd = passwd;
        m_dbname = db;
        //mysql的编码
        mysql_query(m_mysql, "set names utf8;");
        cout << "connect mysql success!\r\n";
        return true;
    }
​
    cout << "connect mysql failed!\r\n";
    return false;
}
QueryResultPtr MySQLTool::Query(const string& sql)
{
    if (m_mysql == NULL) {
        if (connect(m_host, m_user, m_passwd, m_dbname) == false) {
            return QueryResultPtr();
        }
    }
    cout << __FILE__ << "(" << __LINE__ << ")\r\n";
    //blob real_query 遇到\0,不会认为是字符串结束了
    int ret = mysql_real_query(m_mysql, sql.c_str(), sql.size());
    if (ret) {
        uint32_t nErrno = mysql_errno(m_mysql);
        cout << "mysql_real_query call failed! code is :" << nErrno << std::endl;
        if (CR_SERVER_GONE_ERROR == nErrno) {
            if (connect(m_host, m_user, m_passwd, m_dbname) == false) {
                return QueryResultPtr();
            }
            //mysql_real_query 与 mysql_query的区别就是 mysql_real_query遇到/0不会认为是结束
            //因为后面有sql.size()
            ret = mysql_real_query(m_mysql, sql.c_str(), sql.size());
            if (ret) {
                nErrno = mysql_errno(m_mysql);
                cout << "mysql_real_query call failed again! code is :" << nErrno << std::endl;
                return QueryResultPtr();
            }
        }
        else {
            return QueryResultPtr();
        }
​
    }
    cout << __FILE__ << "(" << __LINE__ << ")\r\n";
    MYSQL_RES* result = mysql_store_result(m_mysql);
    uint32_t rowcount = mysql_affected_rows(m_mysql);
    uint32_t cloumncount = mysql_field_count(m_mysql);
    cout << __FILE__ << "(" << __LINE__ << ")\r\n";
    return QueryResultPtr(new QueryResult(result, rowcount, cloumncount));
}
​
bool MySQLTool::Execute(const string& sql)
{
    uint32_t nAffectedCount;
    int nErrno;
    return Execute(sql, nAffectedCount, nErrno);
}
​
bool MySQLTool::Execute(const string& sql, uint32_t& nAffectedCount, int& nErrno)
{
    if (m_mysql == NULL) {
        if (connect(m_host, m_user, m_passwd, m_dbname) == false) {
            return false;
        }
    }
    int ret = mysql_query(m_mysql, sql.c_str());
    if (ret) {
        uint32_t nErrno = mysql_errno(m_mysql);
        cout << "mysql_query call failed! code is :" << nErrno << std::endl;
        cout << "mysql_query call failed! msg :" << mysql_error(m_mysql) << std::endl;
        if (CR_SERVER_GONE_ERROR == nErrno) {
            if (connect(m_host, m_user, m_passwd, m_dbname) == false) {
                return false;
            }
            ret = mysql_query(m_mysql, sql.c_str());
            if (ret) {
                nErrno = mysql_errno(m_mysql);
                cout << "mysql_query call failed again! code is :" << nErrno << std::endl;
                return false;
            }
        }
        else {
            return false;
        }
        nErrno = 0;
        nAffectedCount = mysql_affected_rows(m_mysql);
    }
    return false;
}

查询结果

头文件

#include <unistd.h>
#include <mysql/mysql.h>
#include <stdio.h>
#include <string>
#include <sys/types.h>
#include <errno.h>
#include <memory>
#include <vector>
#include "base/Logging.h"
#include "Field.h"
​
using namespace std;
​
class QueryResult
{
public:
    QueryResult(MYSQL_RES* result, uint32_t rowcount, uint32_t cloumncout);
    ~QueryResult();
    bool NextRow();//true表示还有下一行,并且切换成功;false表示没有了
    Field* Fetch() {
        return m_CurrentRow.data();
    }
    const Field& operator[](int index)const {
        return m_CurrentRow[index];
    }
    const Field& operator[](const string& name)const {
        return m_CurrentRow[GetFieldIndexByName(name)];
    }
    uint32_t GetFieldCount()const { return m_cloumncout; }
    uint32_t GetRowCount()const { return m_rowcount; }
​
    vector<string> const& GetFieldNames() const { return m_vecFieldName; }
    void EndQuery();
    Field::DataTypes toEDYType(enum_field_types mysqltype)const;
protected:
    int GetFieldIndexByName(const string& name) const{
        for (uint32_t i = 0; i < m_vecFieldName.size(); i++) {
            if (m_vecFieldName[i] == name)return i;
        }
        return -1;
    }
private:
    vector<Field> m_CurrentRow;
    vector<string> m_vecFieldName;
    MYSQL_RES* m_result;
    uint32_t m_rowcount;
    uint32_t m_cloumncout;
};
​
typedef shared_ptr<QueryResult> QueryResultPtr;

cpp文件

#include "QueryResult.h"
#include <iostream>
using namespace std;
QueryResult::QueryResult(MYSQL_RES* result, uint32_t rowcount, uint32_t cloumncout)
    :m_result(result), m_rowcount(rowcount), m_cloumncout(cloumncout)
{
    m_CurrentRow.resize(m_cloumncout);
    m_vecFieldName.resize(m_cloumncout);
    MYSQL_FIELD* fields = mysql_fetch_fields(m_result);
    MYSQL_ROW row = mysql_fetch_row(m_result);
    if (row == NULL) {
        EndQuery();
        return;
    }
    //cout << __FILE__ << "(" << __LINE__ << ")\r\n";
    unsigned long* pFieldLength = mysql_fetch_lengths(m_result);
    for (uint32_t i = 0; i < m_cloumncout; i++)
    {
        m_vecFieldName[i] = fields[i].name;
        m_CurrentRow[i].SetType(toEDYType(fields[i].type));
        m_CurrentRow[i].SetName(m_vecFieldName[i]);
        if (row[i] == NULL)
        {
            m_CurrentRow[i].SetValue(NULL, 0);
        }
        else {
            //cout << __LINE__ << ")QueryResult: " << row[i] << " length:" << pFieldLength[i] << endl;
            m_CurrentRow[i].SetValue(row[i], pFieldLength[i]);
        }
    }
    //cout << __FILE__ << "(" << __LINE__ << ")\r\n";
}
​
QueryResult::~QueryResult() {}
bool QueryResult::NextRow()
{
    if (m_result == NULL)return false;
    MYSQL_ROW row = mysql_fetch_row(m_result);
    if (row == NULL) {
        EndQuery();
        return false;
    }
    unsigned long* pFieldLength = mysql_fetch_lengths(m_result);
    for (uint32_t i = 0; i < m_cloumncout; i++)
    {
        if (row[i] == NULL)
        {
            m_CurrentRow[i].SetValue(NULL, 0);
        }
        else {
            m_CurrentRow[i].SetValue(row[i], pFieldLength[i]);
        }
    }
    return true;
}
​
void QueryResult::EndQuery()
{
    m_CurrentRow.clear();
    m_vecFieldName.clear();
    if (m_result) {
        mysql_free_result(m_result);
        m_result = NULL;
    }
    m_rowcount = 0;
    m_cloumncout = 0;
}
​
Field::DataTypes QueryResult::toEDYType(enum_field_types mysqltype)const
{
    switch (mysqltype)
    {
    case FIELD_TYPE_TIMESTAMP:
    case FIELD_TYPE_DATE:
    case FIELD_TYPE_TIME:
    case FIELD_TYPE_DATETIME:
    case FIELD_TYPE_YEAR:
    case FIELD_TYPE_STRING:
    case FIELD_TYPE_VAR_STRING:
    case FIELD_TYPE_BLOB:
    case FIELD_TYPE_SET:
        return Field::EDY_TYPE_STRING;
    case FIELD_TYPE_NULL:
        return Field::EDY_TYPE_NULL;
    case FIELD_TYPE_TINY:
    case FIELD_TYPE_SHORT:
    case FIELD_TYPE_LONG:
    case FIELD_TYPE_LONGLONG:
    case FIELD_TYPE_INT24:
    case FIELD_TYPE_ENUM:
        return Field::EDY_TYPE_INTEGER;
    case FIELD_TYPE_DECIMAL:
    case FIELD_TYPE_FLOAT:
    case FIELD_TYPE_DOUBLE:
        return Field::EDY_TYPE_FLOAT;
    default:
        return Field::EDY_TYPE_NONE;
    }
    return Field::EDY_TYPE_NONE;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值