: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.关闭数据库句柄.
整体的流程不变,把不一样的部分抽象出来 —— 绑定参数,执行串链的过程抽象出来。

绑定参数,如


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

执行查询建链过程,如


  1. int create_userinfo_T(sqlite3_stmt,void * arg)

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


  1. #ifndef _DBHELPER_H_
  2. #define _DBHELPER_H_
  3. #include <sqlite3.h>
  4. #define DB_SQL_MAX_LEN 1024
  5. //执行没有返回的SQL语句
  6. int db_nonquery_operator(const char *sqlstr,int (*bind)(sqlite3_stmt *,int index,void * arg),void *param);
  7. //执行没有返回的SQL语句的多值传参
  8. int db_nonquery_by_varpara(const char *sql,const char *fmt,...);
  9. //执行没有返回的SQL语句
  10. int db_nonquery_transaction(int (*exec_sqls)(sqlite3 *db,void * arg),void *arg);
  11. //执行多值传参的查询语句
  12. int db_query_by_varpara(const char *sql,int (*create)(sqlite3_stmt *stmt,void *arg),void *arg,const char *fmt,...);
  13. //执行查询并返回查询结果集的条数
  14. int db_query_count_result(const char *sql);
  15. //对sqlite3_column_blob的二次封装
  16. int db_stmt_get_blob(sqlite3_stmt *stmt,int index,unsigned char *out);
  17. //对sqlite3_column_text的二次封装
  18. int db_stmt_get_text(sqlite3_stmt *stmt,int index,char *out);
  19. //对sqlite3_column_int的二次封装
  20. int db_stmt_get_int(sqlite3_stmt *stmt,int index);
  21. //对sqlite3_column_double的二次封装
  22. double db_stmt_get_double(sqlite3_stmt *stmt,int index);
  23. #endif

dbhelper.c:


  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <pthread.h>
  4. #include "na_queue.h"
  5. #include "dbhelper.h"
  6. #define DB_NAME "test.db"
  7. static pthread_mutex_t db_mutex_lock = PTHREAD_MUTEX_INITIALIZER;
  8. static int db_bind_by_var(sqlite3_stmt *stmt,const char *fmt,va_list args)
  9. {
  10. int len,npara=1;
  11. int ret = SQLITE_OK;
  12. if(fmt == NULL){
  13. return ret;
  14. }
  15. for(;*fmt;++fmt){
  16. if(*fmt != '%')
  17. continue;
  18. ++fmt;
  19. //get length
  20. len = 0;
  21. while(isdigit(*fmt)){
  22. len = len * 10 + (*fmt - '0');
  23. ++fmt;
  24. }
  25. switch(*fmt){
  26. case 'd':
  27. ret = sqlite3_bind_int(stmt,npara,va_arg(args,int));
  28. break;
  29. case 's':
  30. {
  31. char *str = va_arg(args,char *);
  32. ret = sqlite3_bind_text(stmt,npara,str,strlen(str),NULL);
  33. }
  34. break;
  35. case 'x':
  36. {
  37. unsigned char *pdata;
  38. pdata = va_arg(args,char *);
  39. ret = sqlite3_bind_blob(stmt,npara,pdata,len,NULL);
  40. // printf_phex("blob",pdata,len);
  41. }
  42. break;
  43. default:
  44. ret = SQLITE_ERROR;
  45. break;
  46. }
  47. ++npara;
  48. if(ret)
  49. return ret;
  50. }
  51. return ret;
  52. }
  53. /*
  54. * === FUNCTION ======================================================================
  55. * Name: db_query_by_varpara
  56. * Description: 数据库查询操作,可以带变参绑定
  57. * @sql : sql
  58. * @create : 取得数据并创建节点
  59. * @arg : 用户用于create的参数
  60. * @fmt : 格式字符串,%s string,%d int,%nx 长度为N的二进制串
  61. * ... : 变参
  62. * Return : 查询到数据的条数
  63. * =====================================================================================
  64. */
  65. int db_query_by_varpara(const char *sql,int (*create)(sqlite3_stmt *stmt,void *arg),void *arg,const char *fmt,...)
  66. {
  67. sqlite3 *db = NULL;
  68. sqlite3_stmt *stmt = NULL;
  69. if(sql == NULL){
  70. // return SQLITE_ERROR;
  71. return 0;
  72. }
  73. pthread_mutex_lock(&db_mutex_lock);
  74. int rc = sqlite3_open(DB_NAME,&db);
  75. if(rc != SQLITE_OK){
  76. printf("open database failed,rc=%d",rc);
  77. pthread_mutex_unlock(&db_mutex_lock);
  78. return 0;
  79. }
  80. rc = sqlite3_prepare(db,sql,-1,&stmt,NULL);
  81. if(rc != SQLITE_OK){
  82. printf("database prepare fail,rc=%d",rc);
  83. goto DB_EXEC_FAIL;
  84. }
  85. if(fmt){
  86. va_list args;
  87. va_start(args,fmt);
  88. rc = db_bind_by_var(stmt,fmt,args);
  89. va_end(args);
  90. if(rc){
  91. printf("database bind fail,rc=%d",rc);
  92. goto DB_EXEC_FAIL;
  93. }
  94. }
  95. if(create){
  96. rc = (*create)(stmt,arg);
  97. }else{
  98. rc = (sqlite3_step(stmt),0);
  99. }
  100. sqlite3_finalize(stmt);
  101. goto DB_EXEC_OK;
  102. DB_EXEC_FAIL:
  103. printf("db operator failed,rc=%d",rc);
  104. rc = 0;
  105. DB_EXEC_OK:
  106. sqlite3_close(db);
  107. pthread_mutex_unlock(&db_mutex_lock);
  108. return rc;
  109. }
  110. /*
  111. * === FUNCTION ======================================================================
  112. * Name: db_exec_noquery
  113. * Description: 执行非查询操作
  114. * @sqlstr : sql,多条语句由';'分开
  115. * @bind : 绑定sql中的未知变量操作
  116. * @param : 绑定中的参数
  117. * @bind.index: sql语句序号
  118. * Return : 0 or error
  119. * =====================================================================================
  120. */
  121. int db_nonquery_operator(const char *sqlstr,int (*bind)(sqlite3_stmt *,int index,void * arg),void *param)
  122. {
  123. sqlite3 *db = NULL;
  124. sqlite3_stmt *stmt = NULL;
  125. // char *emsg = NULL;
  126. if(sqlstr == NULL){
  127. return SQLITE_ERROR;
  128. }
  129. pthread_mutex_lock(&db_mutex_lock);
  130. int rc = sqlite3_open(DB_NAME,&db);
  131. if(rc != SQLITE_OK){
  132. printf("open database failed,rc=%d",rc);
  133. pthread_mutex_unlock(&db_mutex_lock);
  134. return rc;
  135. }
  136. rc = sqlite3_exec(db,"begin transaction",0,0,NULL);
  137. if(rc != SQLITE_OK){
  138. printf("begin transaction:ret=%d",rc);
  139. goto DB_BEGIN_FAIL;
  140. }
  141. char sql[DB_SQL_MAX_LEN];
  142. int index = 0,offset=0,n=0;
  143. while(sqlstr[index] != 0){
  144. offset = 0;
  145. do{
  146. if(offset >= DB_SQL_MAX_LEN){
  147. printf("sql is too long,(%d)",offset);
  148. rc = SQLITE_ERROR;
  149. goto DB_EXEC_FAIL;
  150. }
  151. if((sqlstr[index] != ';') && (sqlstr[index] != 0)){
  152. sql[offset++] = sqlstr[index++];
  153. }else{
  154. sql[offset] = '\0';
  155. if(sqlstr[index] == ';') index++;
  156. n++;
  157. break;
  158. }
  159. }while(1);
  160. printf("sql:%s",sql);
  161. rc = sqlite3_prepare(db,sql,-1,&stmt,NULL);
  162. if(rc != SQLITE_OK){
  163. printf("prepare,error,%d",rc);
  164. goto DB_EXEC_FAIL;
  165. }
  166. if(bind){
  167. rc = (*bind)(stmt,n,param);
  168. }else{
  169. rc = sqlite3_step(stmt);
  170. }
  171. sqlite3_finalize(stmt);
  172. if((rc != SQLITE_OK) && (rc != SQLITE_DONE)){
  173. printf("bind");
  174. goto DB_EXEC_FAIL;
  175. }
  176. }
  177. rc = sqlite3_exec(db,"commit transaction",0,0,NULL);
  178. if(rc){
  179. printf("commit transaction:%d",rc);
  180. goto DB_EXEC_FAIL;
  181. }
  182. goto DB_EXEC_OK;
  183. DB_EXEC_FAIL:
  184. if(sqlite3_exec(db,"rollback transaction",0,0,NULL)){
  185. printf("rollback transaction error");
  186. }
  187. DB_BEGIN_FAIL:
  188. // sqlite3_free(emsg);
  189. printf("db operator failed,rc=%d",rc);
  190. DB_EXEC_OK:
  191. sqlite3_close(db);
  192. pthread_mutex_unlock(&db_mutex_lock);
  193. return rc;
  194. }
  195. int db_nonquery_by_varpara(const char *sql,const char *fmt,...)
  196. {
  197. sqlite3 *db = NULL;
  198. sqlite3_stmt *stmt = NULL;
  199. if(sql == NULL){
  200. return SQLITE_ERROR;
  201. }
  202. pthread_mutex_lock(&db_mutex_lock);
  203. int rc = sqlite3_open(DB_NAME,&db);
  204. if(rc != SQLITE_OK){
  205. printf("open database failed,rc=%d",rc);
  206. pthread_mutex_unlock(&db_mutex_lock);
  207. return rc;
  208. }
  209. printf("sql:%s",sql);
  210. rc = sqlite3_prepare(db,sql,-1,&stmt,NULL);
  211. if(rc != SQLITE_OK){
  212. printf("prepare,");
  213. goto DB_EXEC_FAIL;
  214. }
  215. if(fmt){
  216. va_list args;
  217. va_start(args,fmt);
  218. rc = db_bind_by_var(stmt,fmt,args);
  219. va_end(args);
  220. if(rc){
  221. goto DB_EXEC_FAIL;
  222. }
  223. }
  224. rc = sqlite3_step(stmt);
  225. sqlite3_finalize(stmt);
  226. if((rc != SQLITE_OK) && (rc != SQLITE_DONE)){
  227. printf("bind");
  228. goto DB_EXEC_FAIL;
  229. }
  230. rc = 0;
  231. goto DB_EXEC_OK;
  232. DB_EXEC_FAIL:
  233. DB_BEGIN_FAIL:
  234. printf("db operator failed,rc=%d",rc);
  235. DB_EXEC_OK:
  236. sqlite3_close(db);
  237. pthread_mutex_unlock(&db_mutex_lock);
  238. return rc;
  239. }
  240. int db_nonquery_transaction(int (*exec_sqls)(sqlite3 *db,void * arg),void *arg)
  241. {
  242. sqlite3 *db = NULL;
  243. sqlite3_stmt *stmt = NULL;
  244. // char *emsg = NULL;
  245. pthread_mutex_lock(&db_mutex_lock);
  246. int rc = sqlite3_open(DB_NAME,&db);
  247. if(rc != SQLITE_OK){
  248. printf("open database failed,rc=%d",rc);
  249. pthread_mutex_unlock(&db_mutex_lock);
  250. return rc;
  251. }
  252. rc = sqlite3_exec(db,"begin transaction",0,0,NULL);
  253. if(rc != SQLITE_OK){
  254. printf("begin transaction:%d",rc);
  255. goto DB_BEGIN_FAIL;
  256. }
  257. if(exec_sqls){
  258. rc = (*exec_sqls)(db,arg);
  259. }else{
  260. rc = SQLITE_ERROR;
  261. }
  262. if((rc != SQLITE_OK) && (rc != SQLITE_DONE)){
  263. printf("prepare,error,%d",rc);
  264. goto DB_EXEC_FAIL;
  265. }
  266. rc = sqlite3_exec(db,"commit transaction",0,0,NULL);
  267. if(rc){
  268. printf("commit transaction:%d",rc);
  269. goto DB_EXEC_FAIL;
  270. }
  271. goto DB_EXEC_OK;
  272. DB_EXEC_FAIL:
  273. if(sqlite3_exec(db,"rollback transaction",0,0,NULL)){
  274. printf("rollback transaction:error");
  275. }
  276. DB_BEGIN_FAIL:
  277. // sqlite3_free(emsg);
  278. printf("db operator failed,rc=%d",rc);
  279. DB_EXEC_OK:
  280. sqlite3_close(db);
  281. pthread_mutex_unlock(&db_mutex_lock);
  282. return rc;
  283. }
  284. static int db_get_count(sqlite3_stmt *stmt,void *arg)
  285. {
  286. int ret,*count=arg;
  287. ret = sqlite3_step(stmt);
  288. if(ret != SQLITE_ROW)
  289. return SQLITE_EMPTY;
  290. *count = db_stmt_get_int(stmt,0);
  291. return SQLITE_OK;
  292. }
  293. /*
  294. * === FUNCTION ======================================================================
  295. * Name: db_query_count_result
  296. * Description: 查询计数结果的第一列第一行,其它忽略
  297. * @sql : 查询计数的SQL语句
  298. * Return : 查询到计数返回计数,否则一律返回0
  299. * =====================================================================================
  300. */
  301. int db_query_count_result(const char *sql)
  302. {
  303. int ret,count=0;
  304. ret = db_query_by_varpara(sql,db_get_count,&count,NULL);
  305. if(ret == SQLITE_OK)
  306. return count;
  307. return 0;
  308. }
  309. int db_stmt_get_blob(sqlite3_stmt *stmt,int index,unsigned char *out)
  310. {
  311. const char *pdata = sqlite3_column_blob(stmt,index);
  312. int len = sqlite3_column_bytes(stmt,index);
  313. if(pdata){
  314. memcpy(out,pdata,len);
  315. return len;
  316. }
  317. return 0;
  318. }
  319. int db_stmt_get_text(sqlite3_stmt *stmt,int index,char *out)
  320. {
  321. const unsigned char *pdata = sqlite3_column_text(stmt,index);
  322. if(pdata){
  323. int len = strlen(pdata);
  324. strncpy(out,pdata,len);
  325. return len;
  326. }
  327. return 0;
  328. }
  329. int db_stmt_get_int(sqlite3_stmt *stmt,int index)
  330. {
  331. return sqlite3_column_int(stmt,index);
  332. }
  333. double db_stmt_get_double(sqlite3_stmt *stmt,int index)
  334. {
  335. return sqlite3_column_double(stmt,index);
  336. }

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

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

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

首先重写数据模型:


  1. typedef struct userinfo_s{
  2. int userid;
  3. char username[32];
  4. na_queue_t queue;
  5. }userinfo_t;

释放函数链表函数:


  1. void free_userinfo_t(na_queue_t *h){
  2. na_queue_t *head = h,*pos,*n;
  3. userinfo_t *p = NULL;
  4. na_queue_for_each_safe(pos,n,head){
  5. p = na_queue_data(pos,userinfo_t,queue);
  6. free(p);
  7. }
  8. na_queue_init(head);
  9. }

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


  1. int bind_userinfo_t(sqlite3_stmt * stmt,int index,void * arg){
  2. int rc;
  3. userinfo_t * param = arg;
  4. sqlite3_bind_int(stmt,1,param->userid);
  5. sqlite3_bind_text(stmt,2,param->username,strlen(param->username),NULL);
  6. rc = sqlite3_step(stmt);
  7. if (rc != SQLITE_DONE)
  8. return rc;
  9. return SQLITE_OK;
  10. }

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


  1. int create_userinfo_t(sqlite3_stmt * stmt,void * arg){
  2. na_queue_t * h = arg;
  3. na_queue_init(h);
  4. userinfo_t * u;
  5. int ret,count = 0;
  6. ret = sqlite3_step(stmt);
  7. if(ret != SQLITE_ROW){
  8. return 0;
  9. }
  10. do
  11. {
  12. u = calloc(sizeof(userinfo_t),1);
  13. if(!u){
  14. goto CREATE_USERINFO_FAIL;
  15. }
  16. u->userid = db_stmt_get_int(stmt,0);
  17. db_stmt_get_text(stmt,1,u->username);
  18. na_queue_insert_tail(h,&(u->queue));
  19. count ++;
  20. } while ((ret = sqlite3_step(stmt)) == SQLITE_ROW);
  21. return count;
  22. CREATE_USERINFO_FAIL:
  23. free_userinfo_t(h);
  24. return 0;
  25. }

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


  1. //打印用户信息
  2. void printusers(na_queue_t *h){
  3. userinfo_t * q=NULL;
  4. na_queue_foreach(q,h,userinfo_t,queue){
  5. printf("userid:%d username:%s\n",q->userid,q->username);
  6. }
  7. }
  8. //得到所以用户信息
  9. int get_all_userinfo(na_queue_t * h){
  10. return db_query_by_varpara("select * from userinfo;",create_userinfo_t,h,NULL);
  11. }
  12. //添加一个用户信息
  13. int add_a_userinfo(userinfo_t * u){
  14. return db_nonquery_operator("insert into userinfo(userid,username) values (?,?)",bind_userinfo_t,u);
  15. }
  16. int main(int argc, char *argv[])
  17. {
  18. printf("test get all userinfo\n");
  19. na_queue_t h;
  20. int ret = get_all_userinfo(&h);
  21. printusers(&h);
  22. free_userinfo_t(&h);
  23. printf("test add userinfo");
  24. userinfo_t newuser;
  25. newuser.userid = 7;
  26. strncpy(newuser.username,"White",10);
  27. add_a_userinfo(&newuser);
  28. get_all_userinfo(&h);
  29. printusers(&h);
  30. free_userinfo_t(&h);
  31. return 0;
  32. }

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

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. 常用数据库的驱动程序及JDBC URL:

    Oracle数据库: 驱动程序包名:ojdbc14.jar 驱动类的名字:oracle.jdbc.driver.OracleDriver JDBC URL:jdbc:oracle:thin:@dbip ...

  2. rabbitmq method之queue.declare

    queue.declare即申请队列,首先对队列名作处理,若未指定队列名则随机生成一个,然后查询数据库队列是否已经创建,若创建完成则会申请队列返回 handle_method(#'queue.decl ...

  3. sublime 添加代码片段(snippets)

    1.工具-新代码片段(Tools -> New Snippet) 2. <snippet> <content><![CDATA[ if(\$rs && ...

  4. zx一篇让Java程序猿随时可以翻看的Oracle总结

    一篇让Java程序猿随时可以翻看的Oracle总结 前言:Oracle学习也有十几天了,但是呢,接下来还要学习许多其他的东西,并不能提步不前,所以在此总结了以下Oracle中常用的命令和语句,没有语法 ...

  5. pycharm licenseserver 注册方法

    pycharm5.0之后,以前的很多注册码都无法使用,可以选择使用license server 方式进行注册,方法如下: 注册方法:    在 注册时选择 License server ,填 http ...

  6. Leetcode: Word Squares && Summary: Another Important Implementation of Trie(Retrieve all the words with a given Prefix)

    Given a set of words (without duplicates), find all word squares you can build from them. A sequence ...

  7. Linux 安装记录

    ######ubuntu-16.04.1-desktop-amd64 ||| Unity desktop Environment, NOT !!! ######deepin-15.3-amd64.is ...

  8. javascript 中的 let 作用域

    let 声明了一个块级域的局部变量,并且可以给它一个初始化值. 语法EDIT let var1 [= value1] [, var2 [= value2]] [, ..., varN [= value ...

  9. vue.js 批量删除跟全选,反选效果

    <!DOCTYPE html><html lang="en"> <head> <meta charset="UTF-8" ...

  10. android nfc中MifareClassic格式的读写

    Android支持的数据格式 数据格式的Intent filter AndroidManifest.xml文件中,要像向下列示例那样,在<activity>元素内的<meta-dat ...