【c操作mysql】极简封装,两行代码插入任何表单

/*************************************************************************
	> File Name: mysqlTest.c
	> Author:Gin.TaMa 
	> Mail:1137554811@qq.com 
	> Created Time: 2019年03月23日 星期六 09时51分25秒
 ************************************************************************/
#include<iostream>
#include<string>
#include<string.h>
#include<sstream>
#include<stdio.h>
#include<stdlib.h>
#include<vector>
#include<mysql/mysql.h>

using namespace std;

#define Fn_apply(type,fn,...){\
    int tmp[] = {0};type *stopper_for_apply = (type*)tmp;\
    type* list_for_apply[] = {__VA_ARGS__,stopper_for_apply};\
    for(int i = 0;list_for_apply[i] != stopper_for_apply;i ++){\
        fn(list_for_apply[i]);}\
}

#define Free_all(...) Fn_apply(void,free,__VA_ARGS__);

typedef struct mysqlCLR{
    char * server;
    char * user;
    char * passwd;
    char * db;
    unsigned int port;
    MYSQL*mysql;
}mysqlClr;

void freeMysqlClr(mysqlClr*clr){
    Free_all(clr->server,clr->user,clr->passwd,clr->db); 
    mysql_close(clr->mysql);
}

int connectDatabase(mysqlClr* clr){
    clr->mysql = mysql_init(NULL);
    if(mysql_real_connect(clr->mysql,clr->server,clr->user,clr->passwd,clr->db,0,NULL,0)){
        return 1;
    }else{
        perror("wrong connect");
        return 0;
    }
}

#define coutFn(string){sin <<"'" << string << "',";}

#define getInsertSQL(s,tables,...){\
    ostringstream sin;\
    sin << "insert into "<<tables<<" ("<<#__VA_ARGS__<<") values (";\
    Fn_apply(char,coutFn,__VA_ARGS__);\
    s = sin.str();s[s.length() - 1] = ')';}

// 插入算是封装完了
#define inserDataNew(clr,...){\
    string query;\
    getInsertSQL(query,__VA_ARGS__);\
    if(mysql_query(clr.mysql,query.c_str())){\
        cout << "query failde " << query << endl;}\
}

// fetchAll 封装完毕
int fetchAll(mysqlClr*clr,string tables,void(*dofetch)(MYSQL_ROW,void*),void* arg){
    MYSQL* tmp = clr -> mysql;
    string a = "select * from "+tables;

    if(mysql_query(tmp,a.c_str())){
        printf("wrong\n");
        return 0;
    }

    MYSQL_RES *res;     //行的一个查询结果集
    res = mysql_store_result(tmp);

    int i = 0;
    MYSQL_ROW column;   //数据行的列

    while(column = mysql_fetch_row(res)){
        dofetch(column,arg);
        i ++;
    }

    return i;
}
/
// 使用
// 某个表单
typedef struct types{
    char* tid;
    char* tname;
}types;

// 回调函数用来填充数据的
void getTypes(MYSQL_ROW c,void* arg_){
    vector<types*>* arg = (vector<types*>*)arg_;
    types* tmp = new types();
    tmp->tid = strdup(c[0]);
    tmp->tname = strdup(c[1]);
    arg -> push_back(tmp);
}

int main(){

    // 初始化
    mysqlClr clr;
    asprintf(&clr.server,"localhost");
    asprintf(&clr.user,"root");
    asprintf(&clr.passwd,"536842");
    asprintf(&clr.db,"piHealth");
    clr.port = 3306;

    if(!connectDatabase(&clr)){
        return -1;
    }

    vector<types*> t;

    // 插入
    char tid[] = "1";
    char tname[] = "aa";
    // 这个是可变参的。
    inserDataNew(clr,/*表名*/,tid,tname);
    
    // 取数据
    fetchAll(&clr,"types",getTypes,(void*)&t);

    for(auto item:t){
        printf("%s:%s\n",item->tid,item->tname);
    }

    freeMysqlClr(&clr);

    return 0;
}

这个就是使用变参宏实现的一个封装,

比如对于这个样的表单

+-----+-------+
| tid | tname |
+-----+-------+

我要插入一个条记录只用写两行代码

char tid[] = "1";char tname[] = "aa";
inserDataNew(clr,/*表名*/,tid,tname);

而且是具有扩展性。

对于这个表,只要这么写就OK了

+----------+--------------+------+-----+---------+----------------+
| Field    | Type         | Null | Key | Default | Extra          |
+----------+--------------+------+-----+---------+----------------+
| nid      | int(11)      | NO   | PRI | NULL    | auto_increment |
| ntime    | datetime(5)  | YES  |     | NULL    |                |
| nip      | varchar(20)  | NO   |     | NULL    |                |
| ntypes   | int(5)       | NO   |     | NULL    |                |
| ndetails | varchar(255) | NO   |     | NULL    |                |
+----------+--------------+------+-----+---------+----------------+
    char nid[] = "123";
    char ntime[] = "qqq";
    char nip[] = "123456";
    char ntypes[] = "12345";
    char ndetails[] = "yes";

    inserDataNew(clr,"notes_events",nid,ntime,nip,ntypes,ndetails);

使用还是蛮简单的啦。