:first-child{margin-top:0!important}img.plugin{box-shadow:0 1px 3px rgba(0,0,0,.1);border-radius:3px}iframe{border:0}figure{-webkit-margin-before:0;-webkit-margin-after:0;-webkit-margin-start:0;-webkit-margin-end:0}kbd{border:1px solid #aaa;-moz-border-radius:2px;-webkit-border-radius:2px;border-radius:2px;-moz-box-shadow:1px 2px 2px #ddd;-webkit-box-shadow:1px 2px 2px #ddd;box-shadow:1px 2px 2px #ddd;background-color:#f9f9f9;background-image:-moz-linear-gradient(top,#eee,#f9f9f9,#eee);background-image:-o-linear-gradient(top,#eee,#f9f9f9,#eee);background-image:-webkit-linear-gradient(top,#eee,#f9f9f9,#eee);background-image:linear-gradient(top,#eee,#f9f9f9,#eee);padding:1px 3px;font-family:inherit;font-size:.85em}.oembeded .oembed_photo{display:inline-block}img[data-echo]{margin:25px 0;width:100px;height:100px;background:url(../img/ajax.gif) center center no-repeat #fff}.spinner{display:inline-block;width:10px;height:10px;margin-bottom:-.1em;border:2px solid rgba(0,0,0,.5);border-top-color:transparent;border-radius:100%;-webkit-animation:spin 1s infinite linear;animation:spin 1s infinite linear}.spinner:after{content:'';display:block;width:0;height:0;position:absolute;top:-6px;left:0;border:4px solid transparent;border-bottom-color:rgba(0,0,0,.5);-webkit-transform:rotate(45deg);transform:rotate(45deg)}@-webkit-keyframes spin{to{-webkit-transform:rotate(360deg)}}@keyframes spin{to{transform:rotate(360deg)}}p.toc{margin:0!important}p.toc ul{padding-left:10px}p.toc>ul{padding:10px;margin:0 10px;display:inline-block;border:1px solid #ededed;border-radius:5px}p.toc li,p.toc ul{list-style-type:none}p.toc li{width:100%;padding:0;overflow:hidden}p.toc li a::after{content:"."}p.toc li a:before{content:"• "}p.toc h5{text-transform:uppercase}p.toc .title{float:left;padding-right:3px}p.toc .number{margin:0;float:right;padding-left:3px;background:#fff;display:none}input.task-list-item{margin-left:-1.62em}.markdown{font-family:"Hiragino Sans GB","Microsoft YaHei",stheiti,simsun,"Lucida Grande","Lucida Sans Unicode","Lucida Sans",'Segoe UI',applesdgothicneo-medium,'Malgun Gothic',verdana,tahoma,sans-serif;padding:20px}.markdown a{text-decoration:none;vertical-align:baseline}.markdown a:hover{text-decoration:underline}.markdown h1{font-size:2.2em;font-weight:700;margin:1.5em 0 1em}.markdown h2{font-size:1.8em;font-weight:700;margin:1.275em 0 .85em}.markdown h3{font-size:1.6em;font-weight:700;margin:1.125em 0 .75em}.markdown h4{font-size:1.4em;font-weight:700;margin:.99em 0 .66em}.markdown h5{font-size:1.2em;font-weight:700;margin:.855em 0 .57em}.markdown h6{font-size:1em;font-weight:700;margin:.75em 0 .5em}.markdown h1+p,.markdown h1:first-child,.markdown h2+p,.markdown h2:first-child,.markdown h3+p,.markdown h3:first-child,.markdown h4+p,.markdown h4:first-child,.markdown h5+p,.markdown h5:first-child,.markdown h6+p,.markdown h6:first-child{margin-top:0}.markdown hr{border:1px solid #ccc}.markdown p{margin:1em 0;word-wrap:break-word}.markdown ol{list-style-type:decimal}.markdown li{display:list-item;line-height:1.4em}.markdown blockquote{margin:1em 20px}.markdown blockquote>:first-child{margin-top:0}.markdown blockquote>:last-child{margin-bottom:0}.markdown blockquote cite:before{content:'\2014 \00A0'}.markdown .code{border-radius:3px;word-wrap:break-word}.markdown pre{border-radius:3px;word-wrap:break-word;border:1px solid #ccc;overflow:auto;padding:.5em}.markdown pre code{border:0;display:block}.markdown pre>code{font-family:consolas,inconsolata,courier,monospace;font-weight:700;white-space:pre;margin:0}.markdown code{border-radius:3px;word-wrap:break-word;border:1px solid #ccc;padding:0 5px;margin:0 2px}.markdown img{max-width:100%}.markdown mark{color:#000;background-color:#fcf8e3}.markdown table{padding:0;border-collapse:collapse;border-spacing:0;margin-bottom:16px}.markdown table tr td,.markdown table tr th{border:1px solid #ccc;margin:0;padding:6px 13px}.markdown table tr th{font-weight:700}.markdown table tr th>:first-child{margin-top:0}.markdown table tr th>:last-child{margin-bottom:0}.markdown table tr td>:first-child{margin-top:0}.markdown table tr td>:last-child{margin-bottom:0}@import url(http://fonts.googleapis.com/css?family=Roboto+Condensed:300italic,400italic,700italic,400,300,700);.haroopad{padding:20px;color:#222;font-size:15px;font-family:"Roboto Condensed",tauri,"Hiragino Sans GB","Microsoft YaHei",stheiti,simsun,"Lucida Grande","Lucida Sans Unicode","Lucida Sans",'Segoe UI',applesdgothicneo-medium,'Malgun Gothic',verdana,tahoma,sans-serif;background:#fff;line-height:1.6;-webkit-font-smoothing:antialiased}.haroopad a{color:#3269a0}.haroopad a:hover{color:#4183c4}.haroopad h2{border-bottom:1px solid #e6e6e6}.haroopad h6{color:#777}.haroopad hr{border:1px solid #e6e6e6}.haroopad blockquote>code,.haroopad h1>code,.haroopad h2>code,.haroopad h3>code,.haroopad h4>code,.haroopad h5>code,.haroopad h6>code,.haroopad li>code,.haroopad p>code,.haroopad td>code{font-family:consolas,"Liberation Mono",menlo,courier,monospace;font-size:85%;background-color:rgba(0,0,0,.02);padding:.2em .5em;border:1px solid #efefef}.haroopad pre>code{font-size:1em;letter-spacing:-1px;font-weight:700}.haroopad blockquote{border-left:4px solid #e6e6e6;padding:0 15px;color:#777}.haroopad table{background-color:#fafafa}.haroopad table tr td,.haroopad table tr th{border:1px solid #e6e6e6}.haroopad table tr:nth-child(2n){background-color:#f2f2f2}.hljs{display:block;overflow-x:auto;padding:.5em;background:#23241f;-webkit-text-size-adjust:none}.aspectj .hljs-function,.css .hljs-function .hljs-preprocessor,.css .hljs-rules,.css .hljs-value,.hljs,.hljs-pragma,.hljs-tag{color:#f8f8f2}.hljs-emphasis,.hljs-strong,.hljs-strongemphasis{color:#a8a8a2}.alias .hljs-keyword,.hljs-blockquote,.hljs-bullet,.hljs-hexcolor,.hljs-horizontal_rule,.hljs-literal,.hljs-number,.hljs-regexp{color:#ae81ff}.css .hljs-class,.hljs-class .hljs-title:last-child,.hljs-code,.hljs-tag .hljs-value,.hljs-title{color:#a6e22e}.hljs-link_url{font-size:80%}.hljs-strong,.hljs-strongemphasis{font-weight:700}.hljs-class .hljs-title:last-child,.hljs-emphasis,.hljs-strongemphasis,.hljs-typename{font-style:italic}.alias .hljs-keyword:first-child,.css .hljs-important,.css .hljs-tag,.css .unit,.hljs-attribute,.hljs-change,.hljs-flow,.hljs-function,.hljs-header,.hljs-keyword,.hljs-symbol,.hljs-symbol .hljs-string,.hljs-tag .hljs-title,.hljs-value,.hljs-winutils,.nginx .hljs-title,.ruby .hljs-class .hljs-keyword:first-child,.ruby .hljs-function .hljs-keyword,.tex .hljs-special{color:#f92672}.css .hljs-attribute,.hljs-aspect .hljs-keyword:first-child,.hljs-class .hljs-keyword:first-child,.hljs-constant,.hljs-function .hljs-keyword,.hljs-typename{color:#66d9ef}.hljs-aspect .hljs-title,.hljs-class .hljs-title,.hljs-params,.hljs-variable{color:#f8f8f2}.apache .hljs-cbracket,.apache .hljs-tag,.css .hljs-id,.django .hljs-filter .hljs-argument,.django .hljs-template_tag,.django .hljs-variable,.hljs-addition,.hljs-attr_selector,.hljs-built_in,.hljs-envvar,.hljs-link_label,.hljs-link_url,.hljs-prompt,.hljs-pseudo,.hljs-stream,.hljs-string,.hljs-subst,.hljs-type,.ruby .hljs-class .hljs-parent,.smalltalk .hljs-array,.smalltalk .hljs-class,.smalltalk .hljs-localvars,.tex .hljs-command{color:#e6db74}.apache .hljs-sqbracket,.hljs-annotation,.hljs-comment,.hljs-decorator,.hljs-deletion,.hljs-doctype,.hljs-javadoc,.hljs-pi,.hljs-shebang,.tex .hljs-formula{color:#75715e}.coffeescript .javascript,.javascript .xml,.php .xml,.tex .hljs-formula,.xml .css,.xml .hljs-cdata,.xml .javascript,.xml .php,.xml .vbscript{opacity:.5}.mathjax_hover_frame{border-radius:.25em;-webkit-border-radius:.25em;-moz-border-radius:.25em;-khtml-border-radius:.25em;box-shadow:0 0 15px #83a;-webkit-box-shadow:0 0 15px #83a;-moz-box-shadow:0 0 15px #83a;-khtml-box-shadow:0 0 15px #83a;border:1px solid #a6d!important;display:inline-block;position:absolute}.mathjax_hover_arrow{position:absolute;width:15px;height:11px;cursor:pointer}#mathjax_about{position:fixed;left:50%;width:auto;text-align:center;border:3px outset;padding:1em 2em;background-color:#ddd;color:#000;cursor:default;font-family:message-box;font-size:120%;font-style:normal;text-indent:0;text-transform:none;line-height:normal;letter-spacing:normal;word-spacing:normal;word-wrap:normal;white-space:nowrap;float:none;z-index:201;border-radius:15px;-webkit-border-radius:15px;-moz-border-radius:15px;-khtml-border-radius:15px;box-shadow:0 10px 20px gray;-webkit-box-shadow:0 10px 20px gray;-moz-box-shadow:0 10px 20px gray;-khtml-box-shadow:0 10px 20px gray;filter:progid:dximagetransform.microsoft.dropshadow(offx=2, offy=2, color='gray', positive='true')}.mathjax_menu{position:absolute;background-color:#fff;color:#000;width:auto;padding:2px;border:1px solid #ccc;margin:0;cursor:default;font:menu;text-align:left;text-indent:0;text-transform:none;line-height:normal;letter-spacing:normal;word-spacing:normal;word-wrap:normal;white-space:nowrap;float:none;z-index:201;box-shadow:0 10px 20px gray;-webkit-box-shadow:0 10px 20px gray;-moz-box-shadow:0 10px 20px gray;-khtml-box-shadow:0 10px 20px gray;filter:progid:dximagetransform.microsoft.dropshadow(offx=2, offy=2, color='gray', positive='true')}.mathjax_menuitem{padding:2px 2em;background:0 0}.mathjax_menuarrow{position:absolute;right:.5em;color:#666}.mathjax_menuactive .mathjax_menuarrow{color:#fff}.mathjax_menuarrow.rtl{left:.5em;right:auto}.mathjax_menucheck{position:absolute;left:.7em}.mathjax_menucheck.rtl{right:.7em;left:auto}.mathjax_menuradiocheck{position:absolute;left:1em}.mathjax_menuradiocheck.rtl{right:1em;left:auto}.mathjax_menulabel{padding:2px 2em 4px 1.33em;font-style:italic}.mathjax_menurule{border-top:1px solid #ccc;margin:4px 1px 0}.mathjax_menudisabled{color:graytext}.mathjax_menuactive{background-color:highlight;color:highlighttext}.mathjax_menu_close{position:absolute;width:31px;height:31px;top:-15px;left:-15px}#mathjax_zoom{position:absolute;background-color:#f0f0f0;overflow:auto;display:block;z-index:301;padding:.5em;border:1px solid #000;margin:0;font-weight:400;font-style:normal;text-align:left;text-indent:0;text-transform:none;line-height:normal;letter-spacing:normal;word-spacing:normal;word-wrap:normal;white-space:nowrap;float:none;box-shadow:5px 5px 15px #aaa;-webkit-box-shadow:5px 5px 15px #aaa;-moz-box-shadow:5px 5px 15px #aaa;-khtml-box-shadow:5px 5px 15px #aaa;filter:progid:dximagetransform.microsoft.dropshadow(offx=2, offy=2, color='gray', positive='true')}#mathjax_zoomoverlay{position:absolute;left:0;top:0;z-index:300;display:inline-block;width:100%;height:100%;border:0;padding:0;margin:0;background-color:#fff;opacity:0;filter:alpha(opacity=0)}#mathjax_zoomframe{position:relative;display:inline-block;height:0;width:0}#mathjax_zoomeventtrap{position:absolute;left:0;top:0;z-index:302;display:inline-block;border:0;padding:0;margin:0;background-color:#fff;opacity:0;filter:alpha(opacity=0)}.mathjax_preview{color:#888}#mathjax_message{position:fixed;left:1px;bottom:2px;background-color:#e6e6e6;border:1px solid #959595;margin:0;padding:2px 8px;z-index:102;color:#000;font-size:80%;width:auto;white-space:nowrap}#mathjax_msie_frame{position:absolute;top:0;left:0;width:0;z-index:101;border:0;margin:0;padding:0}.mathjax_error{color:#c00;font-style:italic}footer{position:fixed;font-size:.8em;text-align:right;bottom:0;margin-left:-25px;height:20px;width:100%}
-->


事实上对于操作sqlite的其他语言,写一个统一的数据库操作模型是非常容易的,比如java,c#,这些语言支持垃圾回收,支持异常捕获,支持泛型,写起来就很容易。但是对于C语言,就得另当别论了,就拿查询操作来说,c语言没有泛型,不能返回统一的泛型列表,只能返回数据模型的链表结构。

但是得益于前面讲过的通用链表)结构,我们可以尽可能的像其他语言一样封装一个通用的数据库操作模型。

回顾前面讲到的sqlite操作基本流程,查询流程是
1.打开数据库
2.准备好SQL语句。
3.绑定SQL语句参数
4.执行SQL语句
5.返回结果集,执行串链操作。
6.释放资源
7.关闭数据库句柄.
整体的流程不变,把不一样的部分抽象出来 —— 绑定参数,执行串链的过程抽象出来。

绑定参数,如


int bind_userinfo_t(sqlite3_stmt * stmt,int index, void * arg )

执行查询建链过程,如


int create_userinfo_T(sqlite3_stmt,void * arg)

然后在通用的数据库操作函数中传入函数指针,尽量的精简代码。
下面是的dbhelper.h 和 dbhelper.c 抽象的一般数据库操作函数。


#ifndef _DBHELPER_H_
#define _DBHELPER_H_
#include <sqlite3.h> #define DB_SQL_MAX_LEN 1024
//执行没有返回的SQL语句
int db_nonquery_operator(const char *sqlstr,int (*bind)(sqlite3_stmt *,int index,void * arg),void *param);
//执行没有返回的SQL语句的多值传参
int db_nonquery_by_varpara(const char *sql,const char *fmt,...);
//执行没有返回的SQL语句
int db_nonquery_transaction(int (*exec_sqls)(sqlite3 *db,void * arg),void *arg);
//执行多值传参的查询语句
int db_query_by_varpara(const char *sql,int (*create)(sqlite3_stmt *stmt,void *arg),void *arg,const char *fmt,...);
//执行查询并返回查询结果集的条数
int db_query_count_result(const char *sql);
//对sqlite3_column_blob的二次封装
int db_stmt_get_blob(sqlite3_stmt *stmt,int index,unsigned char *out);
//对sqlite3_column_text的二次封装
int db_stmt_get_text(sqlite3_stmt *stmt,int index,char *out);
//对sqlite3_column_int的二次封装
int db_stmt_get_int(sqlite3_stmt *stmt,int index);
//对sqlite3_column_double的二次封装
double db_stmt_get_double(sqlite3_stmt *stmt,int index); #endif

dbhelper.c:


#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include "na_queue.h"
#include "dbhelper.h" #define DB_NAME "test.db" static pthread_mutex_t db_mutex_lock = PTHREAD_MUTEX_INITIALIZER; static int db_bind_by_var(sqlite3_stmt *stmt,const char *fmt,va_list args)
{
int len,npara=1;
int ret = SQLITE_OK;
if(fmt == NULL){
return ret;
} for(;*fmt;++fmt){
if(*fmt != '%')
continue;
++fmt;
//get length
len = 0;
while(isdigit(*fmt)){
len = len * 10 + (*fmt - '0');
++fmt;
}
switch(*fmt){
case 'd':
ret = sqlite3_bind_int(stmt,npara,va_arg(args,int));
break;
case 's':
{
char *str = va_arg(args,char *);
ret = sqlite3_bind_text(stmt,npara,str,strlen(str),NULL);
}
break;
case 'x':
{
unsigned char *pdata;
pdata = va_arg(args,char *);
ret = sqlite3_bind_blob(stmt,npara,pdata,len,NULL);
// printf_phex("blob",pdata,len);
}
break;
default:
ret = SQLITE_ERROR;
break;
}
++npara;
if(ret)
return ret;
}
return ret;
} /*
* === FUNCTION ======================================================================
* Name: db_query_by_varpara
* Description: 数据库查询操作,可以带变参绑定
* @sql : sql
* @create : 取得数据并创建节点
* @arg : 用户用于create的参数
* @fmt : 格式字符串,%s string,%d int,%nx 长度为N的二进制串
* ... : 变参
* Return : 查询到数据的条数
* =====================================================================================
*/
int db_query_by_varpara(const char *sql,int (*create)(sqlite3_stmt *stmt,void *arg),void *arg,const char *fmt,...)
{
sqlite3 *db = NULL;
sqlite3_stmt *stmt = NULL;
if(sql == NULL){
// return SQLITE_ERROR;
return 0;
}
pthread_mutex_lock(&db_mutex_lock);
int rc = sqlite3_open(DB_NAME,&db);
if(rc != SQLITE_OK){
printf("open database failed,rc=%d",rc);
pthread_mutex_unlock(&db_mutex_lock);
return 0;
} rc = sqlite3_prepare(db,sql,-1,&stmt,NULL);
if(rc != SQLITE_OK){
printf("database prepare fail,rc=%d",rc);
goto DB_EXEC_FAIL;
} if(fmt){
va_list args;
va_start(args,fmt);
rc = db_bind_by_var(stmt,fmt,args);
va_end(args);
if(rc){
printf("database bind fail,rc=%d",rc);
goto DB_EXEC_FAIL;
}
} if(create){
rc = (*create)(stmt,arg);
}else{
rc = (sqlite3_step(stmt),0);
}
sqlite3_finalize(stmt);
goto DB_EXEC_OK;
DB_EXEC_FAIL:
printf("db operator failed,rc=%d",rc);
rc = 0;
DB_EXEC_OK:
sqlite3_close(db);
pthread_mutex_unlock(&db_mutex_lock);
return rc;
} /*
* === FUNCTION ======================================================================
* Name: db_exec_noquery
* Description: 执行非查询操作
* @sqlstr : sql,多条语句由';'分开
* @bind : 绑定sql中的未知变量操作
* @param : 绑定中的参数
* @bind.index: sql语句序号
* Return : 0 or error
* =====================================================================================
*/
int db_nonquery_operator(const char *sqlstr,int (*bind)(sqlite3_stmt *,int index,void * arg),void *param)
{
sqlite3 *db = NULL;
sqlite3_stmt *stmt = NULL;
// char *emsg = NULL;
if(sqlstr == NULL){
return SQLITE_ERROR;
}
pthread_mutex_lock(&db_mutex_lock);
int rc = sqlite3_open(DB_NAME,&db);
if(rc != SQLITE_OK){
printf("open database failed,rc=%d",rc);
pthread_mutex_unlock(&db_mutex_lock);
return rc;
}
rc = sqlite3_exec(db,"begin transaction",0,0,NULL);
if(rc != SQLITE_OK){
printf("begin transaction:ret=%d",rc);
goto DB_BEGIN_FAIL;
}
char sql[DB_SQL_MAX_LEN];
int index = 0,offset=0,n=0;
while(sqlstr[index] != 0){
offset = 0;
do{
if(offset >= DB_SQL_MAX_LEN){
printf("sql is too long,(%d)",offset);
rc = SQLITE_ERROR;
goto DB_EXEC_FAIL;
}
if((sqlstr[index] != ';') && (sqlstr[index] != 0)){
sql[offset++] = sqlstr[index++];
}else{
sql[offset] = '\0';
if(sqlstr[index] == ';') index++;
n++;
break;
}
}while(1);
printf("sql:%s",sql);
rc = sqlite3_prepare(db,sql,-1,&stmt,NULL);
if(rc != SQLITE_OK){
printf("prepare,error,%d",rc);
goto DB_EXEC_FAIL;
}
if(bind){
rc = (*bind)(stmt,n,param);
}else{
rc = sqlite3_step(stmt);
}
sqlite3_finalize(stmt);
if((rc != SQLITE_OK) && (rc != SQLITE_DONE)){
printf("bind");
goto DB_EXEC_FAIL;
}
}
rc = sqlite3_exec(db,"commit transaction",0,0,NULL);
if(rc){
printf("commit transaction:%d",rc);
goto DB_EXEC_FAIL;
}
goto DB_EXEC_OK;
DB_EXEC_FAIL:
if(sqlite3_exec(db,"rollback transaction",0,0,NULL)){
printf("rollback transaction error");
}
DB_BEGIN_FAIL:
// sqlite3_free(emsg);
printf("db operator failed,rc=%d",rc);
DB_EXEC_OK:
sqlite3_close(db);
pthread_mutex_unlock(&db_mutex_lock);
return rc;
} int db_nonquery_by_varpara(const char *sql,const char *fmt,...)
{
sqlite3 *db = NULL;
sqlite3_stmt *stmt = NULL;
if(sql == NULL){
return SQLITE_ERROR;
}
pthread_mutex_lock(&db_mutex_lock);
int rc = sqlite3_open(DB_NAME,&db);
if(rc != SQLITE_OK){
printf("open database failed,rc=%d",rc);
pthread_mutex_unlock(&db_mutex_lock);
return rc;
}
printf("sql:%s",sql);
rc = sqlite3_prepare(db,sql,-1,&stmt,NULL);
if(rc != SQLITE_OK){
printf("prepare,");
goto DB_EXEC_FAIL;
}
if(fmt){
va_list args;
va_start(args,fmt);
rc = db_bind_by_var(stmt,fmt,args);
va_end(args);
if(rc){
goto DB_EXEC_FAIL;
}
}
rc = sqlite3_step(stmt);
sqlite3_finalize(stmt);
if((rc != SQLITE_OK) && (rc != SQLITE_DONE)){
printf("bind");
goto DB_EXEC_FAIL;
}
rc = 0;
goto DB_EXEC_OK;
DB_EXEC_FAIL:
DB_BEGIN_FAIL:
printf("db operator failed,rc=%d",rc);
DB_EXEC_OK:
sqlite3_close(db);
pthread_mutex_unlock(&db_mutex_lock);
return rc;
} int db_nonquery_transaction(int (*exec_sqls)(sqlite3 *db,void * arg),void *arg)
{
sqlite3 *db = NULL;
sqlite3_stmt *stmt = NULL;
// char *emsg = NULL;
pthread_mutex_lock(&db_mutex_lock);
int rc = sqlite3_open(DB_NAME,&db);
if(rc != SQLITE_OK){
printf("open database failed,rc=%d",rc);
pthread_mutex_unlock(&db_mutex_lock);
return rc;
}
rc = sqlite3_exec(db,"begin transaction",0,0,NULL);
if(rc != SQLITE_OK){
printf("begin transaction:%d",rc);
goto DB_BEGIN_FAIL;
} if(exec_sqls){
rc = (*exec_sqls)(db,arg);
}else{
rc = SQLITE_ERROR;
}
if((rc != SQLITE_OK) && (rc != SQLITE_DONE)){
printf("prepare,error,%d",rc);
goto DB_EXEC_FAIL;
} rc = sqlite3_exec(db,"commit transaction",0,0,NULL);
if(rc){
printf("commit transaction:%d",rc);
goto DB_EXEC_FAIL;
}
goto DB_EXEC_OK;
DB_EXEC_FAIL:
if(sqlite3_exec(db,"rollback transaction",0,0,NULL)){
printf("rollback transaction:error");
}
DB_BEGIN_FAIL:
// sqlite3_free(emsg);
printf("db operator failed,rc=%d",rc);
DB_EXEC_OK:
sqlite3_close(db);
pthread_mutex_unlock(&db_mutex_lock);
return rc;
} static int db_get_count(sqlite3_stmt *stmt,void *arg)
{
int ret,*count=arg;
ret = sqlite3_step(stmt);
if(ret != SQLITE_ROW)
return SQLITE_EMPTY;
*count = db_stmt_get_int(stmt,0);
return SQLITE_OK;
} /*
* === FUNCTION ======================================================================
* Name: db_query_count_result
* Description: 查询计数结果的第一列第一行,其它忽略
* @sql : 查询计数的SQL语句
* Return : 查询到计数返回计数,否则一律返回0
* =====================================================================================
*/
int db_query_count_result(const char *sql)
{
int ret,count=0;
ret = db_query_by_varpara(sql,db_get_count,&count,NULL);
if(ret == SQLITE_OK)
return count;
return 0;
} int db_stmt_get_blob(sqlite3_stmt *stmt,int index,unsigned char *out)
{
const char *pdata = sqlite3_column_blob(stmt,index);
int len = sqlite3_column_bytes(stmt,index);
if(pdata){
memcpy(out,pdata,len);
return len;
}
return 0;
} int db_stmt_get_text(sqlite3_stmt *stmt,int index,char *out)
{
const unsigned char *pdata = sqlite3_column_text(stmt,index);
if(pdata){
int len = strlen(pdata);
strncpy(out,pdata,len);
return len;
}
return 0;
} int db_stmt_get_int(sqlite3_stmt *stmt,int index)
{
return sqlite3_column_int(stmt,index);
} double db_stmt_get_double(sqlite3_stmt *stmt,int index)
{
return sqlite3_column_double(stmt,index);
}

对以上的代码做一下说明:
test.db为数据库文件

为了处理多线程,在对数据库进行操作的时候加了锁。

现在按照通用数据库操作方式重写上次的代码,查询和增加操作。

首先重写数据模型:


typedef struct userinfo_s{
int userid;
char username[32];
na_queue_t queue;
}userinfo_t;

释放函数链表函数:


void free_userinfo_t(na_queue_t *h){
na_queue_t *head = h,*pos,*n;
userinfo_t *p = NULL;
na_queue_for_each_safe(pos,n,head){
p = na_queue_data(pos,userinfo_t,queue);
free(p);
}
na_queue_init(head);
}

绑定函数,用于绑定insert的插入函数


int bind_userinfo_t(sqlite3_stmt * stmt,int index,void * arg){
int rc;
userinfo_t * param = arg;
sqlite3_bind_int(stmt,1,param->userid);
sqlite3_bind_text(stmt,2,param->username,strlen(param->username),NULL);
rc = sqlite3_step(stmt);
if (rc != SQLITE_DONE)
return rc;
return SQLITE_OK;
}

查询操作需要的串链函数:


int create_userinfo_t(sqlite3_stmt * stmt,void * arg){
na_queue_t * h = arg;
na_queue_init(h);
userinfo_t * u;
int ret,count = 0;
ret = sqlite3_step(stmt);
if(ret != SQLITE_ROW){
return 0;
}
do
{
u = calloc(sizeof(userinfo_t),1);
if(!u){
goto CREATE_USERINFO_FAIL;
}
u->userid = db_stmt_get_int(stmt,0);
db_stmt_get_text(stmt,1,u->username);
na_queue_insert_tail(h,&(u->queue));
count ++;
} while ((ret = sqlite3_step(stmt)) == SQLITE_ROW);
return count;
CREATE_USERINFO_FAIL:
free_userinfo_t(h);
return 0;
}

基本的对数据表的操作就是按照这种方式来抽象代码,现在我们来按照这种方式来写一段测试代码:


//打印用户信息
void printusers(na_queue_t *h){
userinfo_t * q=NULL;
na_queue_foreach(q,h,userinfo_t,queue){
printf("userid:%d username:%s\n",q->userid,q->username);
}
} //得到所以用户信息
int get_all_userinfo(na_queue_t * h){
return db_query_by_varpara("select * from userinfo;",create_userinfo_t,h,NULL);
} //添加一个用户信息
int add_a_userinfo(userinfo_t * u){
return db_nonquery_operator("insert into userinfo(userid,username) values (?,?)",bind_userinfo_t,u);
} int main(int argc, char *argv[])
{
printf("test get all userinfo\n");
na_queue_t h;
int ret = get_all_userinfo(&h);
printusers(&h);
free_userinfo_t(&h);
printf("test add userinfo");
userinfo_t newuser;
newuser.userid = 7;
strncpy(newuser.username,"White",10);
add_a_userinfo(&newuser);
get_all_userinfo(&h);
printusers(&h);
free_userinfo_t(&h);
return 0;
}

我们还是上一次的数据库来接着运行,输出:

test get all userinfo
userid:1 username:Alex

userid:2 username:Neo

userid:3 username:Allan

userid:4 username:coby

userid:5 username:micheal

test add userinfo

userid:1 username:Alex

userid:2 username:Neo

userid:3 username:Allan

userid:4 username:coby

userid:5 username:micheal

userid:7 username:White

以上就是一个简单的C语言对SQLITE数据库操作的封装,事实上我们已经把它用在了我们的生产环境,不过生产环境版本相对于这个版本要复杂一点,加入的日志模块,线程模块,而且现在还在继续进化中,但是原理就是这样了,实现上大同小异而已。实例也同样只是写了查询和插入,至于其他操作就有读者自己在这个实例上去添加了。SQLITE小型数据库相对与其他Oracle等其他大型数据库而言,他对SQL的支持没有他们强大,但是对于小型嵌入式系统已经足够了,他们之间的差异只有改天再补充了。今天就到这了。

generated by haroopad

sqlite嵌入式数据库C语言基本操作(2)的更多相关文章

  1. sqlite嵌入式数据库C语言基本操作(1)

    sqlite嵌入式数据库C语言基本操作(1) :first-child{margin-top:0!important}img.plugin{box-shadow:0 1px 3px rgba(0,0, ...

  2. SQLite/嵌入式数据库

    SQLite/嵌入式数据库 的项目要么不使用数据库(一两个文配置文件就可以搞定),要么就会有很多的数据,用到 postgresql,操练sqlite的还没有.现在我有个自己的小测试例子,写个数据库对比 ...

  3. sqlite嵌入式数据库简介及特性

    p.p1 { margin: 0; font: 12px "Helvetica Neue"; color: rgba(69, 69, 69, 1) } p.p2 { margin: ...

  4. [国嵌攻略][182][Sqlite嵌入式数据库移植]

    数据库系统构成 在计算机系统中,保存数据的方式一般有两种: 1.普通文件方式 2.数据库方式 相比于普通文件方式,使用数据库来管理大批量数据具有更高的效率与安全性. 数据库系统一般由三个部分构成 1. ...

  5. Sqlite嵌入式数据库讲解

    在计算机系统中,保存数据的方式一般有两种:1. 普通文件方式2. 数据库方式 相比于普通文件方式,使用数据库来管理大批量数据具有更高的效率与安全性. 数据库系统一般由3个部分构成1. 数据库2. 数据 ...

  6. 数据持久化之嵌入式数据库 SQLite(三)

    阿里P7Android高级架构进阶视频免费学习请点击:https://space.bilibili.com/474380680 SQLite 是 D. Richard Hipp 用 C 语言编写的开源 ...

  7. [Sqlite]--&gt;嵌入式数据库事务理解以及实例操作

    引子: 1. Sqlite在Windows.Linux 和 Mac OS X 上的安装过程 2,嵌入式数据库的安装.建库.建表.更新表结构以及数据导入导出等等具体过程记录 SQLite 事务(Tran ...

  8. SQLite -- 嵌入式关系型数据库

    SQLite -- 嵌入式关系型数据库 1.SQLite的数据类型:Typelessness(无类型) 1,能够保存不论什么类型的数据到表的随意列中 2.支持常见的类型如: NULL, VARCHAR ...

  9. Android SQLite (一) 数据库简介

    大家好,今天来介绍一下SQLite的相关知识,并结合Java实现对SQLite数据库的操作. SQLite是D.Richard Hipp用C语言编写的开源嵌入式数据库引擎.它支持大多数的SQL92标准 ...

随机推荐

  1. Thinking in Java——笔记(16)

    Arrays Why arrays are special There are three issues that distinguish arrays from other types of con ...

  2. Thinking in Java——笔记(13)

    Strings Immutable Strings Objects of the String class are immutable. Every method in the class that ...

  3. java基础总结——开篇

    工作三年多了,一直没时间静下心来好好总结,2016年马上就要过去了.也算是给自己在新一年的一个任务吧!总结java基础,然后再总结javaweb.纯属个人学习总结,总结过程中如有模糊的地方,望各位看官 ...

  4. Zookeeper学习笔记

    ZK ID存放路径 /tmp/zookeeper/myid

  5. 使用OpenSSL为支付宝生成RSA私钥

    通过openssl工具生成RSA的公钥和私钥(opnssl工具可在互联网中下载到,也可以点此下载无线接口包,里面包含此工具)打开openssl文件夹下的bin文件夹,执行openssl.exe文件: ...

  6. CSS 的定位方式和含义

    CSS 的定位方式和含义 总结一下 CSS 的定位方式.CSS 的定位 position 是处理页面布局时非常重要的属性. CSS 中有 3 种基本的定位机制:普通流.浮动和绝对定位. 在没有指定的情 ...

  7. 使用JCIFS获取远程共享文件

    package com.jadyer.util;  import java.io.File; import java.io.FileOutputStream; import java.io.IOExc ...

  8. 常用prototype函数

    $("spcode").value --取得当前页面的值的value,可以赋值 $F('spcode')         --不能赋值 $!spcode             - ...

  9. PHP数组内容不重复组合排列算法

    最近在做ecshop的商品库存模块,分别给一款商品的多个属性组合设置库存,如下图: 一款手机有不同颜色,屏幕尺寸,系统和电量,都要设置不同的库存,如果都要手动选择属性组合,则会耗费很多不必要的时间.假 ...

  10. iOS APP开发的小知识(分享)

          亿合科技小编发现从2007年第一款智能手机横空出世,由此开启了人们的移动智能时代.我们从一开始对APP的陌生,到现在的爱不释手,可见APP开发的出现对我们的生活改变有多巨大.而iOS AP ...