2025-05-19 09:54:33 +08:00
|
|
|
|
#include "MysqlClient.h"
|
|
|
|
|
|
#include "common/Utils.h"
|
2025-09-14 16:00:30 +08:00
|
|
|
|
#include "Spdlogger.h"
|
2025-08-31 14:38:53 +08:00
|
|
|
|
#include <chrono>
|
|
|
|
|
|
using namespace std;
|
|
|
|
|
|
|
|
|
|
|
|
static int64_t GetTimestamp()
|
|
|
|
|
|
{
|
|
|
|
|
|
return chrono::duration_cast<chrono::seconds>(chrono::system_clock::now().time_since_epoch()).count();
|
|
|
|
|
|
}
|
2025-05-19 09:54:33 +08:00
|
|
|
|
|
2025-08-28 18:42:37 +08:00
|
|
|
|
MysqlClient::MysqlClient(MysqlOption option) : option(option)
|
2025-05-19 09:54:33 +08:00
|
|
|
|
{
|
|
|
|
|
|
conn();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
MysqlClient::~MysqlClient()
|
|
|
|
|
|
{
|
|
|
|
|
|
this->close();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-31 14:38:53 +08:00
|
|
|
|
static int64_t g_tickErr {0};
|
|
|
|
|
|
|
2025-05-19 09:54:33 +08:00
|
|
|
|
int MysqlClient::conn()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (mysql_)
|
|
|
|
|
|
{
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
}
|
2025-09-14 16:00:30 +08:00
|
|
|
|
if (GetTimestamp() - g_tickErr <= 10)
|
2025-08-31 14:38:53 +08:00
|
|
|
|
{
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
}
|
2025-05-19 09:54:33 +08:00
|
|
|
|
mysql_ = mysql_init(nullptr);
|
2025-08-31 14:38:53 +08:00
|
|
|
|
MYSQL* ret = mysql_real_connect(mysql_,
|
|
|
|
|
|
option.host.c_str(),
|
|
|
|
|
|
option.user.c_str(),
|
|
|
|
|
|
option.password.c_str(),
|
|
|
|
|
|
option.dbname.c_str(),
|
|
|
|
|
|
option.port, NULL, 0);
|
2025-05-19 09:54:33 +08:00
|
|
|
|
if (ret == NULL)
|
|
|
|
|
|
{
|
2025-07-18 09:08:09 +08:00
|
|
|
|
std::string err = mysql_error(mysql_);
|
2025-05-19 09:54:33 +08:00
|
|
|
|
//Spdlogger::info("[mysql] connect failed: {}", mysql_error(mysql_));
|
|
|
|
|
|
mysql_ = nullptr;
|
2025-08-31 14:38:53 +08:00
|
|
|
|
g_tickErr = GetTimestamp();
|
2025-05-19 09:54:33 +08:00
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2025-08-31 14:38:53 +08:00
|
|
|
|
g_tickErr = 0;
|
2025-05-19 09:54:33 +08:00
|
|
|
|
mysql_query(mysql_, "set names 'utf8';");
|
|
|
|
|
|
}
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool MysqlClient::isConnected()
|
|
|
|
|
|
{
|
|
|
|
|
|
return (mysql_ != nullptr);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void MysqlClient::close()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (mysql_)
|
|
|
|
|
|
{
|
|
|
|
|
|
mysql_close(mysql_);
|
|
|
|
|
|
mysql_ = nullptr;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-31 14:38:53 +08:00
|
|
|
|
static int MysqlQuery(MYSQL* mysql, const std::string& sql)
|
2025-05-19 09:54:33 +08:00
|
|
|
|
{
|
2025-08-31 14:38:53 +08:00
|
|
|
|
int err = 0;
|
|
|
|
|
|
if (!mysql)
|
2025-05-19 09:54:33 +08:00
|
|
|
|
{
|
2025-09-14 16:00:30 +08:00
|
|
|
|
spdlog::error("Mysql exec error, database is not connected.");
|
2025-08-31 14:38:53 +08:00
|
|
|
|
return err;
|
2025-05-19 09:54:33 +08:00
|
|
|
|
}
|
2025-08-26 18:36:25 +08:00
|
|
|
|
if (sql.empty())
|
|
|
|
|
|
{
|
2025-09-14 16:00:30 +08:00
|
|
|
|
spdlog::error("Mysql exec error, sql is empty.");
|
2025-08-31 14:38:53 +08:00
|
|
|
|
return err;
|
2025-08-26 18:36:25 +08:00
|
|
|
|
}
|
2025-08-31 14:38:53 +08:00
|
|
|
|
err = mysql_query(mysql, sql.c_str());
|
|
|
|
|
|
if (0 != err)
|
2025-05-19 09:54:33 +08:00
|
|
|
|
{
|
2025-08-31 14:38:53 +08:00
|
|
|
|
err = mysql_errno(mysql);
|
2025-09-14 16:00:30 +08:00
|
|
|
|
spdlog::error("Mysql exec error: {}, {}, sql={}", err, mysql_error(mysql), sql);
|
2025-08-31 14:38:53 +08:00
|
|
|
|
return err;
|
2025-05-19 09:54:33 +08:00
|
|
|
|
}
|
2025-08-31 14:38:53 +08:00
|
|
|
|
return err;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int MysqlClient::exec(std::string sql)
|
|
|
|
|
|
{
|
|
|
|
|
|
int err = MysqlQuery(mysql_, sql);
|
|
|
|
|
|
// 确保读取并释放结果集,否则会产生 [2014,Commands out of sync;] 错误
|
|
|
|
|
|
MYSQL_RES* res = mysql_store_result(mysql_);
|
|
|
|
|
|
if (res) { mysql_free_result(res); }
|
|
|
|
|
|
return err;
|
2025-05-19 09:54:33 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-31 14:38:53 +08:00
|
|
|
|
int MysqlClient::exec(std::string sql, vector<Fields>& result)
|
2025-05-19 09:54:33 +08:00
|
|
|
|
{
|
|
|
|
|
|
result.clear();
|
2025-08-31 14:38:53 +08:00
|
|
|
|
int err = MysqlQuery(mysql_, sql);
|
|
|
|
|
|
if (err != 0)
|
2025-05-19 09:54:33 +08:00
|
|
|
|
{
|
2025-08-31 14:38:53 +08:00
|
|
|
|
return err;
|
2025-05-19 09:54:33 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
MYSQL_RES* res = mysql_store_result(mysql_);
|
2025-08-31 14:38:53 +08:00
|
|
|
|
if (res)
|
2025-05-19 09:54:33 +08:00
|
|
|
|
{
|
2025-08-31 14:38:53 +08:00
|
|
|
|
vector<string> fieldNames;
|
|
|
|
|
|
while (true)
|
2025-05-19 09:54:33 +08:00
|
|
|
|
{
|
2025-08-31 14:38:53 +08:00
|
|
|
|
MYSQL_FIELD* field = mysql_fetch_field(res);
|
|
|
|
|
|
if (!field)
|
|
|
|
|
|
{
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
fieldNames.push_back(field->name);
|
2025-05-19 09:54:33 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-31 14:38:53 +08:00
|
|
|
|
while (true)
|
2025-05-19 09:54:33 +08:00
|
|
|
|
{
|
2025-08-31 14:38:53 +08:00
|
|
|
|
MYSQL_ROW row = mysql_fetch_row(res);
|
|
|
|
|
|
if (!row)
|
|
|
|
|
|
{
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
2025-05-19 09:54:33 +08:00
|
|
|
|
|
2025-08-31 14:38:53 +08:00
|
|
|
|
Fields rowData;
|
|
|
|
|
|
for (size_t i = 0; i < fieldNames.size(); ++i)
|
|
|
|
|
|
{
|
|
|
|
|
|
string field_text = (row[i] == NULL) ? "" : row[i];
|
|
|
|
|
|
rowData.set(fieldNames[i], field_text);
|
|
|
|
|
|
}
|
|
|
|
|
|
result.push_back(rowData);
|
2025-05-19 09:54:33 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-31 14:38:53 +08:00
|
|
|
|
// 释放结果集
|
|
|
|
|
|
mysql_free_result(res);
|
|
|
|
|
|
}
|
|
|
|
|
|
return 0;
|
2025-05-19 09:54:33 +08:00
|
|
|
|
}
|