您的位置:首页 > 编程语言 > C语言/C++

c语言下的通用数据库接口(之sqlite消化,模拟c#,java的反射)

2014-05-13 20:48 627 查看
在java/C#中都有类的反射,而C下是不存在的。

java/C#中可以把表设计成类,而C下只能设计成结构体形式。

在java中有hibernate来操作数据库,但是在C下面怎么设计好呢?

现在,我想出了一个点子,以下使用sqlite

先创建一个结构体,表示一张数据库表的结构。

typedef struct User {
int id;
char *name;
char *password;

} User;

创建表的语句:

CREATE TABLE 'User' ('id'  INTEGER PRIMARY KEY AUTOINCREMENT,'name' varchar(100),'password'  varchar(100),'workNumber' varchar(100))

数据库的操作有select ,insert ,delete ,update,而insert,delete,update都是让数据库去操作,但select是有返回数据的。

所以,对于insert,delete,update我采用

[cpp]
view plaincopyprint?





int sql_exec(char *format,...) { 

    char sql[1024]; 
    va_list args; 

    char *errmsg=NULL; 
    int rc; 
    va_start(args, format);  
    vsprintf(sql,format,args); 
    va_end(args); 
    rc=sqlite3_exec(g_mdb,sql,NULL,NULL,&errmsg); 
    if(rc!=SQLITE_OK){ 
        printf("%s,%s,%s\n",__FUNCTION__,errmsg,sql); 

        sqlite3_free(errmsg); 
        return SQLITE_ERROR; 

    } 
    return SQLITE_OK; 



int sql_exec(char *format,...) {
char sql[1024];
va_list args;
char *errmsg=NULL;
int rc;
va_start(args, format);
vsprintf(sql,format,args);
va_end(args);
rc=sqlite3_exec(g_mdb,sql,NULL,NULL,&errmsg);
if(rc!=SQLITE_OK){
printf("%s,%s,%s\n",__FUNCTION__,errmsg,sql);
sqlite3_free(errmsg);
return SQLITE_ERROR;
}
return SQLITE_OK;
}
对数据库的操作我定义成

[cpp]
view plaincopyprint?





#define SELECT_(_columns,_table,_where) "select "_columns" from "#_table" WHERE "##_where 

#define INSERT_INTO_(_table,_columns,_values) "insert into "#_table" ("_columns") values ("_values")" 

#define UPDATE_(_table,_set,_where) "UPDATE "#_table" SET "_set" WHERE "##_where 

#define DELETE_FROM(_table,_where) "DELETE FROM "#_table" WHERE "##_where 

#define SELECT_(_columns,_table,_where) "select "_columns" from "#_table" WHERE "##_where
#define INSERT_INTO_(_table,_columns,_values) "insert into "#_table" ("_columns") values ("_values")"
#define UPDATE_(_table,_set,_where) "UPDATE "#_table" SET "_set" WHERE "##_where
#define DELETE_FROM(_table,_where) "DELETE FROM "#_table" WHERE "##_where


#define insert_table(format,...)  sql_exec(format,__VA_ARGS__)

#define update_table(format,...)  sql_exec(format,__VA_ARGS__)

#define delete_table(format,...)  sql_exec(format,__VA_ARGS__)

最终调用(insert):

insert_table(INSERT_INTO_(User,"id,name,password","%d,'%s','%s'"),us.id,us.name,us.password);

而对于select ,返回的是一个列表数据:

[cpp]
view plaincopyprint?





struct select_list { 

    void *value; 
    struct select_list *next; 

}; 
typedef void select_value_free(void *value); 

 
struct select_list *select_list_new(){ 

    struct select_list *h=(struct select_list*)malloc(sizeof(struct select_list)); 

    memset(h,0,sizeof(struct select_list)); 

    return h; 


4000
 
void select_list_free(struct select_list *list,select_value_free value_free){ 

    struct select_list *next; 

    if(list==NULL){ 

        return ; 
    } 
    if(list->value){ 
        value_free(list->value); 
    } 
    if(list) { 
        next=list->next; 
        free(list); 
    } 
    select_list_free(next,value_free); 


struct select_list {
void *value;
struct select_list *next;
};
typedef void select_value_free(void *value);

struct select_list *select_list_new(){
struct select_list *h=(struct select_list*)malloc(sizeof(struct select_list));
memset(h,0,sizeof(struct select_list));
return h;
}

void select_list_free(struct select_list *list,select_value_free value_free){
struct select_list *next;
if(list==NULL){
return ;
}
if(list->value){
value_free(list->value);
}
if(list) {
next=list->next;
free(list);
}
select_list_free(next,value_free);
}


select_list *home;

select_table((void**)&home,SELECT_("id",User,"name='%s' and password='%s'"),us.name,us.password);

if(home!=NULL){
for(next=home;next;next=next->next){
User *item=((User*)next->value);
printf("%d,%s,%s\n",item->id,item->name,item->password);
}
select_list_free(home,user_free);
}

//关键是在select_table

通过sqlite3_prepare查找出sqlite3_stmt,遍历stmt,取出当前操作的表名,与定义的结构体user比较,如果等于,则创建User,把查询的数据给User,再把这个User加入链表value就可以了。

[cpp]
view plaincopyprint?





void *select_value_item_user(sqlite3_stmt *stmt){ 

    int i; 
    int count; 

    User *item=(User*)malloc(sizeof(User)); 

    memset(item,0,sizeof(User)); 

    count=sqlite3_column_count(stmt); 
    for(i=0;i<count;i++){ 

        if(0==strcmp(sqlite3_column_name(stmt,i),"id")){ 

            item->id=sqlite3_column_int(stmt,i); 
        } 
        if(0==strcmp(sqlite3_column_name(stmt,i),"name")){ 

            char_cpy(&item->name,(const
char *)sqlite3_column_text(stmt,i)); 

        } 
    }    
    return item; 



void *select_value_item_user(sqlite3_stmt *stmt){
int i;
int count;
User *item=(User*)malloc(sizeof(User));
memset(item,0,sizeof(User));
count=sqlite3_column_count(stmt);
for(i=0;i<count;i++){
if(0==strcmp(sqlite3_column_name(stmt,i),"id")){
item->id=sqlite3_column_int(stmt,i);
}
if(0==strcmp(sqlite3_column_name(stmt,i),"name")){
char_cpy(&item->name,(const char *)sqlite3_column_text(stmt,i));
}
}
return item;
}


[cpp]
view plaincopyprint?





int select_table(void **result,char *pszFormat,...) { 

    sqlite3_stmt * stmt=NULL;  
    const char *table_name=NULL; 

    int count=0; 
    char sql[1024]; 

    va_list args;  
    struct select_list *next=NULL; 

    struct select_list *home=NULL; 

    va_start(args, pszFormat);  
    vsprintf(sql,pszFormat,args); 
    va_end(args); 
    printf("%s\n",sql); 
    *result=NULL; 
 
    if(sqlite3_prepare(g_mdb,sql,-1,&stmt,NULL)==SQLITE_OK){ 

        while( sqlite3_step(stmt)==SQLITE_ROW){ 

            /************************************************************************/ 

            /*                                                                      */ 

            /************************************************************************/ 

            table_name=sqlite3_column_table_name(stmt,0); 
            if(table_name) { 

                if(strcmp(table_name,STR(User))==0){ 

                    //添加到list就可以了 

                    next=select_list_new(); 
                    next->value=select_value_item_user(stmt); 

                    next->next=NULL; 
                    if(*result==NULL){ 

                        *result=next; 
                    } else { 

                        home->next=next; 
                    } 
                    home=next; 
                } 
            } else { 
                { 
                    int column_count=sqlite3_column_count(stmt); 

                    int i=0; 

                    for(i=0;i<column_count;i++){ 

                        if(sqlite3_column_type(stmt,i)==SQLITE_INTEGER) { 

                            //printf("%s,%d\n",sqlite3_column_name(stmt,i),sqlite3_column_int(stmt,i)); 

                            *result=(void*)sqlite3_column_int(stmt,i); 

                        } 
                    } 
                } 
            } 
            count++; 
        } 
    } else { 
        count=-1; 
        //save errmsg... 
    } 
    sqlite3_finalize(stmt); 
    return count; 



int select_table(void **result,char *pszFormat,...) {
sqlite3_stmt * stmt=NULL;
const char *table_name=NULL;
int count=0;
char sql[1024];
va_list args;
struct select_list *next=NULL;
struct select_list *home=NULL;
va_start(args, pszFormat);
vsprintf(sql,pszFormat,args);
va_end(args);
printf("%s\n",sql);
*result=NULL;

if(sqlite3_prepare(g_mdb,sql,-1,&stmt,NULL)==SQLITE_OK){
while( sqlite3_step(stmt)==SQLITE_ROW){
/************************************************************************/
/*                                                                      */
/************************************************************************/
table_name=sqlite3_column_table_name(stmt,0);
if(table_name) {
if(strcmp(table_name,STR(User))==0){
//添加到list就可以了
next=select_list_new();
next->value=select_value_item_user(stmt);
next->next=NULL;
if(*result==NULL){
*result=next;
} else {
home->next=next;
}
home=next;
}
} else {
{
int column_count=sqlite3_column_count(stmt);
int i=0;
for(i=0;i<column_count;i++){
if(sqlite3_column_type(stmt,i)==SQLITE_INTEGER) {
//printf("%s,%d\n",sqlite3_column_name(stmt,i),sqlite3_column_int(stmt,i));
*result=(void*)sqlite3_column_int(stmt,i);
}
}
}
}
count++;
}
} else {
count=-1;
//save errmsg...
}
sqlite3_finalize(stmt);
return count;
}


这只是针对单一表的查询操作,可以加入count(*)功能。

int count;

select_table((void**)&count,SELECT_("count(*)",User,"1=1"));

对于其它的表,你只要创建一个相当于User的结构体就可以了,再添加一个 select_value_item_user 功能数据库值与此绑定功能的函数,再在select中选择这个函数就可,

当然,可以采用C 下的 HashMap 来把 表名(结构体名)与 绑定函数 做一个映像,这样方便一点,但我的表只有几个所以就不用做了
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: