mirror of
https://github.com/quizhizhe/LiteLoaderBDS-1.16.40.git
synced 2025-06-07 20:28:10 +00:00
208 lines
7.7 KiB
C++
208 lines
7.7 KiB
C++
#include <third-party/mysql/mysql.h>
|
|
#include <DB/Impl/MySQL/Session.h>
|
|
#include <DB/Impl/MySQL/Stmt.h>
|
|
#include <LoggerAPI.h>
|
|
#define OK 0
|
|
|
|
namespace DB {
|
|
|
|
MySQLSession::MySQLSession() {
|
|
IF_ENDBG dbLogger.info("MySQLSession::MySQLSession: Constructed! this: {}", (void*)this);
|
|
conn = mysql_init(nullptr);
|
|
}
|
|
MySQLSession::MySQLSession(const ConnParams& params) {
|
|
IF_ENDBG dbLogger.info("MySQLSession::MySQLSession: Constructed! this: {}", (void*)this);
|
|
conn = mysql_init(nullptr);
|
|
open(params);
|
|
}
|
|
|
|
MySQLSession::~MySQLSession() {
|
|
IF_ENDBG dbLogger.info("MySQLSession::MySQLSession: Destructor: this: {}", (void*)this);
|
|
close();
|
|
}
|
|
|
|
void MySQLSession::setSSL(const ConnParams& params) {
|
|
auto p = params;
|
|
auto key = p.get<std::string>({"sslkey", "ssl_key", "ssl-key"}); // Private key path
|
|
auto cert = p.get<std::string>({"sslcert", "ssl_cert", "ssl-cert"}); // Public certificate path
|
|
auto ca = p.get<std::string>({"sslca", "ssl_ca", "ssl-ca"}); // Certificate authority path
|
|
auto capath = p.get<std::string>({"sslcapath", "ssl_capath", "ssl-capath"}); // Certificate authority directory
|
|
auto cipher = p.get<std::string>({"sslcipher", "ssl_cipher", "ssl-cipher"}); // List of ciphers to use
|
|
if (key.empty() || cert.empty()) {
|
|
return;
|
|
}
|
|
mysql_ssl_set(conn, key.c_str(), cert.c_str(),
|
|
(ca.empty() ? nullptr : ca.c_str()),
|
|
(capath.empty() ? nullptr : capath.c_str()),
|
|
(cipher.empty() ? nullptr : cipher.c_str())); // Always returns 0
|
|
}
|
|
|
|
void MySQLSession::open(const ConnParams& params) {
|
|
auto p = params;
|
|
unsigned long flags = 0;
|
|
uint16_t port = 0;
|
|
if ((port = p.getPort()) == 0) {
|
|
port = 3306;
|
|
}
|
|
std::string db = p.getDatabase();
|
|
if (p.get({"compress"}, true, false)) {
|
|
flags |= CLIENT_COMPRESS;
|
|
}
|
|
if (p.get({"ssl", "ssl_mode", "sslmode", "ssl-mode"}, true, false)) {
|
|
flags |= CLIENT_SSL;
|
|
setSSL(p);
|
|
}
|
|
// auto defaultCharset = mysql_character_set_name(conn);
|
|
auto charset = p.get<std::string>({"charset", "char_set", "characterset", "character_set", "charsetname",
|
|
"char_set_name", "charactersetname", "character_set_name"},
|
|
"true",
|
|
"utf8");
|
|
// IF_ENDBG dbLogger.debug("MySQLSession::open: MySQL default charset name: {}", defaultCharset);
|
|
mysql_options(conn, MYSQL_SET_CHARSET_NAME, charset.c_str());
|
|
auto res = mysql_real_connect(conn, p.getHost().c_str(), p.getUsername().c_str(), p.getPassword().c_str(),
|
|
(db.empty() ? nullptr : db.c_str()), port, nullptr, 0);
|
|
if (!res) {
|
|
throw std::runtime_error("MySQLSession::MySQLSession: Failed to open database: " + std::string(mysql_error(conn)));
|
|
}
|
|
IF_ENDBG dbLogger.debug("MySQLSession::open: Opened database: " + std::string(p.getHost()) + ":" + std::to_string(port) + "/" + db);
|
|
#if defined(LLDB_DEBUG_MODE)
|
|
mysql_dump_debug_info(conn);
|
|
#endif
|
|
}
|
|
|
|
bool MySQLSession::execute(const std::string& query) {
|
|
IF_ENDBG dbLogger.debug("MySQLSession::execute: Executing > " + query);
|
|
auto res = mysql_query(conn, query.c_str());
|
|
return res == OK;
|
|
}
|
|
|
|
bool MySQLSession::relogin(const std::string& user, const std::string& password, const std::string& db) {
|
|
IF_ENDBG dbLogger.debug("MySQLSession::change: Changing user to {} and database to {}", user, db);
|
|
auto res = mysql_change_user(conn, user.c_str(), password.c_str(), (db.empty() ? nullptr : db.c_str()));
|
|
return res == OK;
|
|
}
|
|
|
|
Session& MySQLSession::query(const std::string& query, std::function<bool(const Row&)> callback) {
|
|
IF_ENDBG dbLogger.debug("MySQLSession::query: Querying > " + query);
|
|
auto res = mysql_query(conn, query.c_str());
|
|
if (res != OK) {
|
|
throw std::runtime_error("MySQLSession::query: Failed to query database: " + std::string(mysql_error(conn)));
|
|
}
|
|
auto result = mysql_store_result(conn);
|
|
if (!result) {
|
|
// throw std::runtime_error("MySQLSession::query: Failed to store result: " + std::string(mysql_error(conn)));
|
|
return *this; // No result set
|
|
}
|
|
auto numFields = mysql_num_fields(result);
|
|
auto numRows = mysql_num_rows(result);
|
|
auto fields = mysql_fetch_fields(result);
|
|
IF_ENDBG dbLogger.debug("MySQLSession::query: Query returned {} rows and {} fields", numRows, numFields);
|
|
// Fetch column names
|
|
RowHeader header;
|
|
for (unsigned int i = 0; i < numFields; i++)
|
|
header.add(std::string(fields[i].name, fields[i].name_length));
|
|
// Fetch rows
|
|
while (auto row = mysql_fetch_row(result)) {
|
|
Row r(header);
|
|
for (unsigned int i = 0; i < numFields; i++) {
|
|
auto type = fields[i].type;
|
|
switch (type) {
|
|
case MYSQL_TYPE_TINY:
|
|
case MYSQL_TYPE_SHORT:
|
|
case MYSQL_TYPE_LONG:
|
|
case MYSQL_TYPE_LONGLONG:
|
|
case MYSQL_TYPE_INT24:
|
|
case MYSQL_TYPE_YEAR:
|
|
if (fields[i].flags & UNSIGNED_FLAG)
|
|
r.push_back(std::stoull(row[i]));
|
|
else
|
|
r.push_back(std::stoll(row[i]));
|
|
break;
|
|
case MYSQL_TYPE_FLOAT:
|
|
r.push_back(std::stof(row[i]));
|
|
break;
|
|
case MYSQL_TYPE_DOUBLE:
|
|
r.push_back(std::stod(row[i]));
|
|
break;
|
|
case MYSQL_TYPE_BIT: {
|
|
uint64_t val = 0;
|
|
auto len = fields[i].length;
|
|
for (unsigned int j = 0; j < len; j++) {
|
|
if (row[i][j] == '1')
|
|
val |= (1ULL << j);
|
|
}
|
|
r.push_back(val);
|
|
break;
|
|
}
|
|
case MYSQL_TYPE_STRING:
|
|
case MYSQL_TYPE_VAR_STRING:
|
|
case MYSQL_TYPE_ENUM:
|
|
case MYSQL_TYPE_SET:
|
|
case MYSQL_TYPE_VARCHAR:
|
|
case MYSQL_TYPE_JSON:
|
|
r.push_back(std::string(row[i]));
|
|
break;
|
|
case MYSQL_TYPE_DECIMAL:
|
|
case MYSQL_TYPE_NEWDECIMAL: {
|
|
r.push_back(Any());
|
|
// TODO: Decimal
|
|
break;
|
|
}
|
|
case MYSQL_TYPE_TINY_BLOB:
|
|
case MYSQL_TYPE_MEDIUM_BLOB:
|
|
case MYSQL_TYPE_LONG_BLOB:
|
|
case MYSQL_TYPE_BLOB:
|
|
r.push_back(ByteArray(row[i], row[i] + strlen(row[i])));
|
|
break;
|
|
case MYSQL_TYPE_GEOMETRY:
|
|
default:
|
|
r.push_back(Any());
|
|
break;
|
|
}
|
|
}
|
|
if (!callback(r)) {
|
|
break;
|
|
}
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
SharedPointer<Stmt> MySQLSession::prepare(const std::string& query, bool autoExecute) {
|
|
auto stmt = MySQLStmt::create(getOrSetSelf(), query, autoExecute);
|
|
stmtPool.push_back(stmt);
|
|
return stmt;
|
|
}
|
|
|
|
std::string MySQLSession::getLastError() const {
|
|
return std::string(mysql_error(conn));
|
|
}
|
|
|
|
uint64_t MySQLSession::getAffectedRows() const {
|
|
return mysql_affected_rows(conn);
|
|
}
|
|
|
|
uint64_t MySQLSession::getLastInsertId() const {
|
|
return mysql_insert_id(conn);
|
|
}
|
|
|
|
void MySQLSession::close() {
|
|
if (conn) {
|
|
mysql_close(conn);
|
|
conn = nullptr;
|
|
IF_ENDBG dbLogger.debug("MySQLSession::close: Closed database");
|
|
}
|
|
}
|
|
|
|
bool MySQLSession::isOpen() {
|
|
return mysql_ping(conn) == OK;
|
|
}
|
|
|
|
DBType MySQLSession::getType() {
|
|
return DBType::MySQL;
|
|
}
|
|
|
|
SharedPointer<Stmt> MySQLSession::operator<<(const std::string& query) {
|
|
return prepare(query, true);
|
|
}
|
|
|
|
} // namespace DB
|