封装MySQL的C语言API

为方便使用,对MySQL提供的C语言API进行包装。考虑到在实际使用时,会对多个数据库服务器进行访问,将访问句柄组织成链表进行管理。

封装后的函数有如下几个,函数名均已MY作为前缀:
其中的重要参数,MySQLConnLink是一个链表,其元素为MySQLConnection,该结构中包含了一个数据库连接相关的信息。如:数据库的账号,密码,数据库名字等。

1
2
3
4
5
6
7
8
9
struct MySQLConnection {
    char ip[20]; 
    char account[50];
    char password[50];
    char db_name[50];
    bool is_connected;
    MYSQL mysql_handle;
    MySQLConnection* next_conn;
};

这是链表结构:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
struct MySQLConnLink {
    MySQLConnection head_mysql_conn;
    MySQLConnection* cur_mysql_conn;
    int records_num;
    MYSQL_RES* result;
    MYSQL_ROW cur_row;
    bool is_store_result;
    bool is_cur_result_null;
    bool is_multi_connection;
    char sql_statement[10000];
};

MYInit

在使用该套函数时,第一步要用该函数完成初始化操作。其主要工作是,对传入的MySQLConnLink所维护的各成员做初始化。最重要的是MySQLConnection中的mysql_handle句柄。另外,该函数要求指定是否会对多个数据库服务进行连接(多连接/单链接模式),其它函数会基于此标识来决定是否要对链表实施遍历操作。

MYSetDB

指定要操作的是哪个数据库。该数据库由IP、Port、访问账号,访问密码,库名来标识。函数的主要逻辑:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// 未使用多连接模式,只存在一个连接节点   
if (!conn_link->is_multi_connection) {

    // 当前唯一的连接节点并未对应于指定的数据库服务,做简单处理,仅基于IP判断    
    if (strcmp(conn_link->cur_mysql_conn->ip, ip) != 0) {

        /* 关闭当前连接节点的句柄,重新连接到新指定的数据库服务 */

    } else {// 当前唯一的连接节点恰好对应于指定的数据库服务

        /* 若当前节点尚未对数据库服务进行连接,则连接 */

    }
} else {// 使用了多连接模式,可能有多个连接节点

        /* 遍历链表,寻找与指定数据库相对应的连接节点,若找到,就以该节点作为当前节点 */    
        /* 若找不到,就选一个未与其对应数据库服务建立连接的节点做为当前节点来用 */
        /* 若未与其对应数据库服务建立连接的节点也不存在的话,就创建一个新节点做为当前节点 */

        /* 经过以上步骤,就已确定出“当前节点”,最后,判断一下这个“当前节点”是否已与其对应的数据库服务建立了连接,若没连接,则进行连接 */      
}

/* 然后,调用mysql_select_db选择指定的库 */

/* 最后,更新“当前节点”的数据,如IP地址,数据库名字等 */

MYExecSQL

执行指定的SQL语句,这个语句在MySQLConnLink结构的sql_statement字段中指出。如果要查询执行结果集的话,需要将is_store_result置为真。例如:

1
2
3
sprintf(db_link.sql_statement, "select * from xyz");
db_link.is_store_result = true;
MYExecSQL(&db_link, err_msg);

MYCloseCurDBMYCloseAllDB

MYCloseCurDB函数所谓的Close是将MySQLConnLink中的cur_mysql_conn对应的”当前节点“所维护的MySQL句柄给close掉,它并不会从链表中删除相应的连接节点。而MYCloseAllDB函数除了将链表中每个节点维护的MySQL句柄给Close掉之外,还会将节点销毁。

MYFetchRow

从查询结果集中取一行。取出的内容会放在MySQLConnLink的cur_row字段中。假设被查询的数据表有3个int型字段,下面是使用示例:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
for (int i = 0; i < db_link.records_num; i++) {
    MYFetchRow(&db_link, err_msg);
    int j = 0;
    if (db_link.cur_row[j]) {
        std::cout << atoi(db_link.cur_row[j]) << " ";
    }
    j++;
    if (db_link.cur_row[j]) {
        std::cout << atoi(db_link.cur_row[j]) << " ";
    }
    j++;
    if (db_link.cur_row[j]) {
        std::cout << atoi(db_link.cur_row[j]) << " ";
    }
    std::cout << std::endl;  
}

完整实现:my_db.hmy_db.cc
使用示例:main.cc
工程文件:CMakeLists.txt
数据库:test.sql