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\n",__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\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就能够了。

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

时间: 2024-12-26 11:41:42

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

c 下的通用数据库接口

在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 P

C语言下泊松分布以及指数分布随机数生成器实现

最近实验室的项目需要实现模拟文件访问序列,要求单位时间内的数据请求次数符合泊松分布,而两次请求见的时间间隔符合指数分布.没办法只好重新捡起已经丢掉多时的概率知识.于是也就有了这篇关于在C语言下符合泊松分布和指数分布的随机数生成器的实现. 泊松分布 在实际的事例中,当某一事件,比如进站乘客数量,电话交换机接收到的通话请求以固定的瞬时速率λ独立且随机地出现时,就可以认为该事件在单位时间内发生的次数符合泊松分布. 首先必须由二项分布引出: 如果做一件事情成功的概率是 p 的话,那么独立尝试做这件事情

.NET环境下,通过LINQ操作SQLite数据库

//对应数据库中的某个表 [Table(Name = "main.Student")]    public class Student    {        [Column(Name = "StuName", DbType = "varchar(50)")]        public string StuName { get; set; }        [Column(Name = "StuNo", DbType = &

android下apkplug通用主题(皮肤)切换解决方案之主题包开发-02

该文章是基于apkplug V1.6.8 进行说明的 我们提供了一个demo做为参考,项目下载地址为:http://git.oschina.net/plug/IMThemeDemo 该 IMThemeDemo 实现了简单的聊天泡泡切换功能,同时主题包(插件)是托管在apkplug的云服务器上的.所以要阅读项目的完整代码可以先看插件托管服务开发系列文章 <插件托管服务开发指南> demo运行效果图: 上一篇文章我们实现了主应用的开发,本篇应用我们开发主题包(插件). 一,主题包说明 apkplu

通过伪元素指定不同语言下的引号

要指定不同语言下的引号,只需通过伪元素进行生成即可: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <style type="text/css"> :lang(en) > q {quotes:'"' '"';}

C语言下的简易计算器

1 #include <stdio.h> 2 #include <math.h> 3 int main() 4 { 5 double data1, data2; 6 char op; 7 while (3 == scanf("%lf%c%lf", &data1, &op, &data2) ) 8 { 9 double result; 10 printf("%lf%c%lf=", data1,data2); 11 swi

安装win7英文语言包(通用)

1.下载Vistalizator软件安装 地址:http://www.froggie.sk/download.html 2.下载语言包 地址:http://www.froggie.sk/download.html 说明:如果只下载语言包安装,虽然也是exe文件但是很多时候都无法执行(还没有搞清楚为什么) 3.安装方法. 1)先安装Vistalizator,打开界面如下 2.点击Add languages选择下载完成的语言包 3.点击Install language 4.ok,等待20分钟完成 5

R语言下解决包不能安装的问题

目的:这次主要是为了安装Rcpp包, 方法:install.packages("Rcpp") 结果:出错,,于是,我从官网下载Rcpp_0.11.2.tar.gz,在终端输入 R CMD INSTALL Rcpp_0.11.2.tar.gz,提示我的R语言版本太低,需要3.0以上 改进:卸载R语言2.15版本后,重新安装 1: wget http://cran.r-project.org/src/base/R-2/R-3.1.0.tar.gz 2: tar -xzvf R-3.1.0.

Swift语言下的单例设计模式实现(SINGLETON)

一.意图 保证一个类公有一个实例,并提供一个访问它的全局访问点. 二.使用场景 1.使用场景 当类只能有一个实例而且客户可以从一个众所周知的访问点访问它时 当这个唯一实例应该是通过子类化可扩展的,并且客户应该无需更改代码就能使用一个扩展的实例时. 2.实现的重要三个步骤 私有化构造方法(Swift不支持) 使用一个静态变量保存实例的引用 提供一个全局的访问方法 三. Swift语言下的实现 Swift语言不支持变量及方法的权限,没有办法隐藏变量及方法,可以随意直接创建一个实例.单例的创建有很多写