需在無 MySQL 客戶端環境下程式化導入 SQL 腳本,MySQL C API 無直接 SOURCE 命令對應函數,需自行解析腳本文件逐條執行。本文提供完整的跨平台(Windows/Linux)C++ 封裝實現。
.sql 文件。; 作為語句結束標識(簡易解析,不處理分號在字符串/註釋內的情況)。mysql_real_query() 執行。#ifndef _COMMON_H
#define _COMMON_H
#ifdef WIN32
#include
typedef __int8 int8_t; typedef __int16 int16_t; typedef __int32 int32_t; typedef __int64 int64_t;
typedef unsigned __int8 uint8_t; typedef unsigned __int16 uint16_t; typedef unsigned __int32 uint32_t; typedef unsigned __int64 uint64_t;
#define atoll(_String) _atoi64(_String)
#define PATH_DELIMTER "\\"
#else
#include #include #include #include
#define PATH_DELIMTER "/"
#endif
#include #include #include #include #include
#ifndef _DBMANAGER_H
#define _DBMANAGER_H
#include
using namespace std;
#include "common.h"
#include
struct DBInfo { string host, user, passwd, db; uint16_t port; };
class DBManager {
public:
DBManager(); ~DBManager();
bool ConnectDB(DBInfo &dbInfo);
bool SelectDB(string dbName);
MYSQL_RES* ExeSql(const char *sql, int len);
bool SourceSql(string fileName); // 核心:導入腳本
private:
MYSQL* mysqlInit(DBInfo &info);
void mysqlClose();
bool ReadSqlFile(string fileName, vector &sqlVec); // 解析文件
MYSQL *m_mysqlConn;
DBInfo m_dbConfig;
};
extern DBManager g_DBManager;
#endif
#include "dbmanager.h"
#include
DBManager g_DBManager;
DBManager::DBManager() {}
DBManager::~DBManager() {}
bool DBManager::ConnectDB(DBInfo &dbInfo) {
m_dbConfig = dbInfo;
m_mysqlConn = mysqlInit(dbInfo);
return m_mysqlConn != NULL;
}
MYSQL* DBManager::mysqlInit(DBInfo &info) {
MYSQL *mysql = mysql_init(NULL);
if (!mysql) return NULL;
if (!mysql_real_connect(mysql, info.host.c_str(), info.user.c_str(),
info.passwd.c_str(), info.db.c_str(), info.port, NULL, 0)) {
mysql_close(mysql); return NULL;
}
#if MYSQL_VERSION_ID >= 50013
my_bool reconnect = 1;
mysql_options(mysql, MYSQL_OPT_RECONNECT, &reconnect);
#else
mysql->reconnect = 1;
#endif
return mysql;
}
void DBManager::mysqlClose() {
if (m_mysqlConn) { mysql_close(m_mysqlConn); m_mysqlConn = NULL; }
}
MYSQL_RES* DBManager::ExeSql(const char *sql, int len) {
MYSQL_RES* res = NULL;
int ret = mysql_real_query(m_mysqlConn, sql, len);
if (ret == 0) res = mysql_store_result(m_mysqlConn);
else printf("mysql query %s return errorcode:%d\n", sql, mysql_errno(m_mysqlConn));
return res;
}
bool DBManager::SelectDB(string dbName) {
return mysql_select_db(m_mysqlConn, dbName.c_str()) == 0;
}
bool DBManager::ReadSqlFile(string fileName, vector &sqlVec) {
ifstream in(fileName.c_str(), ios::in);
if (!in) return false;
string line, singleSql;
while (getline(in, line)) {
singleSql += line;
size_t pos = line.find(';');
if (pos != string::npos) { // 遇到分號視為一條語句結束
sqlVec.push_back(singleSql);
singleSql.clear();
}
}
in.close();
return true;
}
bool DBManager::SourceSql(string fileName) {
vector vecSql;
if (!ReadSqlFile(fileName, vecSql)) { printf("導入 %s 失敗\n", fileName.c_str()); return false; }
for (auto &s : vecSql) {
ExeSql(s.c_str(), s.length());
}
return true;
}
DBInfo info = {"localhost", "root", "root", "mydb", 3306};
g_DBManager.ConnectDB(info);
g_DBManager.SourceSql("init_schema.sql");
libsqlparser)或按 MySQL 官方 mysql 客戶端源碼邏輯實現狀態機解析。