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

    在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我採用

    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
    ",__FUNCTION__,errmsg,sql);
    		sqlite3_free(errmsg);
    		return SQLITE_ERROR;
    	}
    	return SQLITE_OK;
    }
    对数据库的操作我定义成

    #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 ,返回的是一个列表数据:

    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 ",item->id,item->name,item->password);
    }
    select_list_free(home,user_free);
    }

    //关键是在select_table

    通过sqlite3_prepare查找出sqlite3_stmt,遍历stmt,取出当前操作的表名。与定义的结构体user比較,假设等于。则创建User,把查询的数据给User,再把这个User增加链表value就能够了。

    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;
    }

    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
    ",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
    ",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 来把 表名(结构体名)与 绑定函数 做一个映像,这样方便一点,但我的表仅仅有几个所以就不用做了。

  • 相关阅读:
    Binary Stirling Numbers
    Count the Buildings ( s1 )
    P3375 【模板】KMP字符串匹配
    POJ2151Check the difficulty of problems
    fbx 模型转换 export
    Linux --windows vs
    phyreengine 3.12.0 安装遇到的问题
    A trip through the graphics pipeline 2011 Part 10(翻译)
    服务端 unity
    nsight 使用问题
  • 原文地址:https://www.cnblogs.com/lcchuguo/p/5349535.html
Copyright © 2011-2022 走看看