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; }