提供型別安全、資源自動管理 (RAII) 的 C++ 薄封裝層,專注於 Prepared Statement (預處理語句) 的參數綁定與結果集映射至 C++ 結構體,減少樣板碼與錯誤處理負擔。
// 連線參數結構
struct MySQL_parm {
std::string host, user, password, database, unixsock;
};
// 連線管理類 (非可複製)
class DBMySQL {
MYSQL* mysqlPtr_;
uint32_t errno_;
// 內部建立 MYSQL_STMT*
MYSQL_STMT* _createSTMT();
public:
DBMySQL(); // mysql_init
void open(const MySQL_parm&); // mysql_real_connect
void close(); // mysql_close
const char* strerr() const; // mysql_error
friend class DBSTMT;
};
// Prepared Statement 封裝 (非可複製)
class DBSTMT {
MYSQL_STMT* stmt_;
public:
DBSTMT(const char* query, DBMySQL& db); // mysql_stmt_init + prepare
void execute(); // 無參數執行
void execute(MYSQL_BIND* bind); // 綁定結果集並執行
void bind(MYSQL_BIND* bind); // 綁定輸入參數
int fetch(); // mysql_stmt_fetch,傳回 0 表成功
~DBSTMT(); // mysql_stmt_close
};
利用巨集簡化 MYSQL_BIND 陣列建立,支援二進位 (字串/Blob) 與整數型別:
#define DECL_BIND(StructName, FieldCount) \
class bind_##StructName : public StructName { \
MYSQL_BIND _bind[FieldCount]; \
my_bool _is_null[FieldCount]; \
unsigned long _length[FieldCount]; \
public: \
bind_##StructName() { \
int i = 0; \
bzero(_bind, sizeof(_bind));
#define BIND_BIN(member, len) \
_bind[i].buffer_type = MYSQL_TYPE_STRING; \
_bind[i].buffer = (char*)&(parent::member); \
_bind[i].buffer_length = len; \
_bind[i].is_null = _is_null + i; \
_bind[i].length = _length + i; \
++i;
#define BIND_INT(member) \
_bind[i].buffer_type = MYSQL_TYPE_LONG; \
_bind[i].buffer = (char*)&(parent::member); \
_bind[i].buffer_length = 0; \
_bind[i].is_null = _is_null + i; \
_bind[i].length = _length + i; \
++i;
#define END_BIND(StructName) \
} \
operator MYSQL_BIND*() { return _bind; } \
};
// 1. 定義資料結構
struct account {
char user[36];
unsigned char password[16];
uint32_t status;
uint32_t id;
};
// 2. 宣告綁定類別 (4 個欄位)
DECL_BIND(account, 4)
BIND_BIN(user, 32)
BIND_BIN(password, 16)
BIND_INT(status)
BIND_INT(id)
END_BIND(account)
// 3. 主程式
int main() {
try {
DBMySQL db;
MySQL_parm parm = {"localhost", "root", "test", "testdb", "/var/lib/mysql/mysql.sock"};
db.open(parm);
// 查詢
DBSTMT stmt_q("SELECT user, password, status, id FROM account", db);
bind_account acc;
stmt_q.execute(acc); // 綁定結果集並執行
while (stmt_q.fetch() == 0) {
printf("%s %u %u\n", acc.user, acc.status, acc.id);
}
// 參數化插入
DBSTMT stmt_i("INSERT INTO account(user, password, status) VALUES (?, ?, ?)", db);
stmt_i.bind(acc); // 綁定輸入參數
// 設定 acc.user/password/status 後...
stmt_i.execute(); // 執行插入
} catch (const char* err) {
fprintf(stderr, "Error: %s\n", err);
}
return 0;
}
MYSQL_BIND 編譯期對應,避免手動填寫索引錯誤。mysql_stmt_close/mysql_close)。const char* 錯誤訊息,簡化上層捕獲。適用場景: 嵌入式系統、高效能服務端、需精細控制 Prepared Statement 行為的 C++ 專案。