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

c 下的通用数据库接口,布布扣,bubuko.com

时间: 2024-10-11 00:59:47

c 下的通用数据库接口的相关文章

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

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

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

android下apkplug通用主题(皮肤)切换解决方案之主应用-01

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

Ubuntu下比较通用的makefile实例

本文转自http://blog.chinaunix.net/uid-20608849-id-360294.html 笔者在写程序的时候会遇到这样的烦恼:一个项目中可能会有很多个应用程序,而新建一个应用程序则所有的Makefile都要重写一遍,虽然可以部分的粘帖复制,但还是感觉应该找到更好的解决途径:另外当一个应用程序中包含多个文件夹时通常要在每个目录下创建一个Makefile,当有数十个文件夹时,要创建如此多的Makefile也是不胜其烦.那么为什么不用automake呢,诚然,对于一个很大的工

再整理:Visual Studio Code(vscode)下的通用C语言环境搭建

版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://www.cnblogs.com/czlhxm/p/11794743.html 参考博客:整理:Visual Studio Code (vscode) 配置C.C++环境/编写运行C.C++(主要Windows.简要Linux) 主要流程: 1.vscode的下载与简单配置 2.MinGw的下载与安装 3.配置系统环境变量 4.修改vscode调试配置文件 5.vscod

Android 下实现通用自启动守护实现

1.Android 操作系统架构 Android 系统分为四个层,从高到底分别是:应用程序层(Application).应用程序 框架层(Application Framework).系统运行库层(Libraries)和 Linux 内核层(Linux Kernel). Android 操作系统最底层还是 Linux 内核,我们就从 Linux 内核开始着手. 2.Linux 配置自启动原理 Linux 加载后, 将初始化硬件和设备驱动, 然后运行第一个进程 init.init 根据配置文件继续

Mac下VIM的DIY配置(Linux下Vim通用)

Mac下VIM的DIY偏好配置 " 首先执行: " cp /usr/share/vim/vimrc ~/.vimrc " 拷贝默认的配置文件 ,然后再执行: " vim ~/.vimrc " 编辑该文件 在文件的最后加入 " syntax on " 保存退出即可 " ==========================下以下是配置内容================== " Configuration file fo

windows和linux平台下的通用时间测试函数

Time.cpp ////////////////////////////////////////////////////////////////////////////// // Timer.cpp // ========= // High Resolution Timer. // This timer is able to measure the elapsed time with 1 micro-second accuracy // in both Windows, Linux and U

EF通用数据层封装类(支持读写分离,一主多从)

浅谈orm 记得四年前在学校第一次接触到 Ling to Sql,那时候瞬间发现不用手写sql语句是多么的方便,后面慢慢的接触了许多orm框架,像 EF,Dapper,Hibernate,ServiceStack.OrmLite 等.当然每种orm都有各自的优势,也有不足的地方.园子里也有很多大神开源了他们写的orm,如SqlSugar,Chloe.ORM,CYQ.Data 等.先不说这些开源的orm使用度怎么样,我觉得起码从开源的精神上就很可嘉了,我也曾下载过这几位大神的源码进行学习. 所有o