第六章 核心API (二)
一、查询参数化
总体而言,绑定函数可分为两类,一类用于标量值(int、double、int64、NULL),另一类用于数组(blob、text和text16)。其中,数组绑定函数需要一个长度参数和指向清理函数的指针。
sqlite3_bind_text()自动转义引号字符。
使用BLOB类型时,绑定函数声明如下:
1 /* 2 ** Bind a blob value to an SQL statement variable. 3 */ 4 int sqlite3_bind_blob( 5 sqlite3_stmt *pStmt, /*语句句柄*/ 6 int i, /*次序*/ 7 const void *zData, /*指向blob数据*/ 8 int nData, /*数据的字节长度*/ 9 void (*xDel)(void*) /*清理处理程序*/ 10 )
对于xDel参数,有两个特殊含义的预定义值。
1 typedef void (*sqlite3_destructor_type)(void*); 2 #define SQLITE_STATIC ((sqlite3_destructor_type)0) 3 #define SQLITE_TRANSIENT ((sqlite3_destructor_type)-1)
- SQLITE_STATIC:告诉绑定函数数组内存驻留在非托管的空间,SQLite不会视图清理该空间。
- SQLITE_TRANSIENT:告诉绑定函数数组内存经常变化,SQLite需要使用自己的数据副本,此副本在语句终结时自动清除。
- 也可提供一个指向自定义的清理函数指针,语句结束时会被自动调用。该函数形式如下:
void cleanup_fn(void*)
1、参数编号
允许为参数指定编号,可设置参数范围1~999。
如下代码,分别指定了100和101位参数的编号。其中参数编号100使用两次,这样可以节省时间。
1 name = "Mackinaw Peaches"; 2 sql = "insert into episodes (id, cid, name) " 3 "values (?100,?100,?101)"; 4 5 rc = sqlite3_prepare(db, sql, (int)strlen(sql), &stmt, &tail); 6 7 if(rc != SQLITE_OK) { 8 fprintf(stderr, "sqlite3_prepare() : Error: %s\n", tail); 9 return rc; 10 } 11 12 sqlite3_bind_int(stmt, 100, 10); 13 sqlite3_bind_text(stmt, 101, name, (int)strlen(name), SQLITE_TRANSIENT); 14 sqlite3_step(stmt); 15 sqlite3_finalize(stmt);
View Code
2、参数命名
允许给参数命名,可在指定参数编号的地方指定一个名称。可使用:或者@。参看示例代码。
1 name = "Mackinaw Peaches"; 2 sql = "insert into episodes (id, cid, name) values (:cosmo,:cosmo,:newman)"; 3 4 rc = sqlite3_prepare(db, sql, (int)strlen(sql), &stmt, &tail); 5 6 if(rc != SQLITE_OK) { 7 fprintf(stderr, "Error: %s\n", tail); 8 return rc; 9 } 10 11 sqlite3_bind_int( stmt, 12 sqlite3_bind_parameter_index(stmt, ":cosmo"), 10); 13 14 sqlite3_bind_text( stmt, 15 sqlite3_bind_parameter_index(stmt, ":newman"), 16 name, 17 (int)strlen(name), cleanup_fn ); 18 19 sqlite3_step(stmt); 20 sqlite3_finalize(stmt);
View Code
与位置参数类似,sqlit3_prepare()也会为命名的参数自动分配序号。可通过sqlite_bind_parameter_index()获得编号。
1 /* 2 ** CAPI3REF: Index Of A Parameter With A Given Name 3 ** METHOD: sqlite3_stmt 4 ** 5 ** ^Return the index of an SQL parameter given its name. ^The 6 ** index value returned is suitable for use as the second 7 ** parameter to [sqlite3_bind_blob|sqlite3_bind()]. ^A zero 8 ** is returned if no matching parameter is found. ^The parameter 9 ** name must be given in UTF-8 even if the original statement 10 ** was prepared from UTF-16 text using [sqlite3_prepare16_v2()] or 11 ** [sqlite3_prepare16_v3()]. 12 ** 13 ** See also: [sqlite3_bind_blob|sqlite3_bind()], 14 ** [sqlite3_bind_parameter_count()], and 15 ** [sqlite3_bind_parameter_name()]. 16 */ 17 SQLITE_API int sqlite3_bind_parameter_index(sqlite3_stmt*, const char *zName);
3、Tcl参数
属于Tcl的特定扩展。
二、错误与异常
1、错误处理
通过如下函数获取给定错误的详细信息,若无错误,将返回”not an error“。
1 /* 2 ** Return UTF-8 encoded English language explanation of the most recent 3 ** error. 4 */ 5 const char *sqlite3_errmsg(sqlite3 *db)
2、繁忙情况处理
1)通过重新运行该语句或采取一些其他操作处理SQLITE_BUSY
2)让SQLite调用繁忙处理程序
该函数提供了调用用户定义函数的方法,而不是立即去阻塞或返回SQLITE_BUSY。该函数提供了繁忙处理函数的第一 个参数,繁忙处理程序的第二个参数是事先向同一个锁事件的处理程序的调用次数。
死锁不会可能不会调用此函数。
SQLITE_API int sqlite3_busy_handler(sqlite3*,int(*)(void*,int),void*);
3)让SQLite调用繁忙处理程序
涉及到sqlite3_busy_timeout()函数。该函数说明了在SQLITE_BUSY前需要等待多长锁清除时间。即使设置足够的时间(30s),仍有必要处理SQLITE_BUSY应急计划。
该函数封装了sqlite3_busy_handler()函数。
int sqlite3_busy_timeout(sqlite3 *db, int ms)
3、模式改变处理
模式更改发生的时间介于编译语句sqlit3_prepare()的调用和执行语句sqlite3_step()的调用之间。此时更改之前发生编译的准备语句将失效。sqlite3_step()调用将尝试重新编译相关的SQL并尽可能正常运行,如果无法重新编译,sqlite3_step()将返回错误码SQLITE_SCHEMA。
以下操作可能会导致SQLITE_SCHEMA错误:
- 分离数据库
- 修改或安装用户自定义的函数或聚合
- 修改或安装用户自定义的排序规则
- 修改或安装授权函数
- 清理数据库空间
处理的每个SQL语句都将传递给第二个参数中指定的回调函数。pArg参数是xTrace的第一个参数。
void *sqlite3_trace(sqlite3 *db, void(*xTrace)(void*,const char*), void *pArg)
三、操作控制
SQLite提供了可以在编译和运行时检视或管理SQL命令的API。这些函数可以安装用来检视数据库的回调函数,通常在各种数据库事件发生时控制这些事件。
1、提交钩子
该函数可检视给定连接上的事务提交事件。函数原型如下:
1 /* 2 ** Register a function to be invoked when a transaction commits. 3 ** If the invoked function returns non-zero, then the commit becomes a 4 ** rollback. 5 */ 6 void *sqlite3_commit_hook( 7 sqlite3 *db, /* Attach the hook to this database */ 8 int (*xCallback)(void*), /* Function to invoke on each commit */ 9 void *pArg /* Argument to the function */ 10 )
如果回调函数返回非零值,提交将装换为回滚。
对于xCallback,如果为NULL,将禁止当前注册函数;如果无注册过,sqlite3_commit_hook()将返回NULL;如果以前注册过,sqlite3_commit_hook()将返回以前的参数data值。
2、回滚钩子
回滚钩子关注给定连接上的回滚事件。
1 /* 2 ** Register a callback to be invoked each time a transaction is rolled 3 ** back by this database connection. 4 */ 5 void *sqlite3_rollback_hook( 6 sqlite3 *db, /* Attach the hook to this database */ 7 void (*xCallback)(void*), /* Callback function */ 8 void *pArg /* Argument to the function */ 9 )
不管是显示的回滚命令、隐式错误还是违反约束导致的回滚。由于数据库连接关闭导致的自动回滚,将如法触发回调函数。与sqlite3_commit_hook()一样,每次调用时,提供新的回调函数将替换以前注册的回调函数。
3、更新钩子
用于检视给定连接上对行的所有更新、插入和删除操作。
1 /* 2 ** Register a callback to be invoked each time a row is updated, 3 ** inserted or deleted using this database connection. 4 */ 5 void *sqlite3_update_hook( 6 sqlite3 *db, /* Attach the hook to this database */ 7 void (*xCallback)(void*,int,char const *,char const *,sqlite_int64), 8 void *pArg /* Argument to the function */ 9 )
xCallback的函数原型如下:
1 void callback(void* data, 2 int operation_code, 3 char const *db_name, 4 char const *table_name, 5 sqlite_int64 rowid);
参数data是由注册函数的pArg参数提供的。
operation_code取值SQLITE_INSET、SQLITE_UPDATE和SQLITE_DELETE。
db_name,table_name对应数据库名称和操作发生的表名称。
rowid为受影响的行。
系统表不会调用回调函数。如果之前存在回调函数,则返回值指向之前注册的回调函数数据的指针。
4、授权函数
允许监控或控制查询语句的编译。
1 SQLITE_API int sqlite3_set_authorizer( 2 sqlite3*, 3 int (*xAuth)(void*,int,const char*,const char*,const char*,const char*), 4 void *pUserData 5 );
回调函数的原型:
1 static int authCallback( 2 void *pClientData, //用户数据 3 int op, //事件代码 4 const char *z1, //事件具体相关的参数 5 const char *z2, //事件具体相关的参数 6 const char *z3, //数据库名称 7 const char *z4 //触发器或视图名称 8 )
参数op、z1、z2取值如下:
1 #define SQLITE_CREATE_INDEX 1 /* Index Name Table Name */ 2 #define SQLITE_CREATE_TABLE 2 /* Table Name NULL */ 3 #define SQLITE_CREATE_TEMP_INDEX 3 /* Index Name Table Name */ 4 #define SQLITE_CREATE_TEMP_TABLE 4 /* Table Name NULL */ 5 #define SQLITE_CREATE_TEMP_TRIGGER 5 /* Trigger Name Table Name */ 6 #define SQLITE_CREATE_TEMP_VIEW 6 /* View Name NULL */ 7 #define SQLITE_CREATE_TRIGGER 7 /* Trigger Name Table Name */ 8 #define SQLITE_CREATE_VIEW 8 /* View Name NULL */ 9 #define SQLITE_DELETE 9 /* Table Name NULL */ 10 #define SQLITE_DROP_INDEX 10 /* Index Name Table Name */ 11 #define SQLITE_DROP_TABLE 11 /* Table Name NULL */ 12 #define SQLITE_DROP_TEMP_INDEX 12 /* Index Name Table Name */ 13 #define SQLITE_DROP_TEMP_TABLE 13 /* Table Name NULL */ 14 #define SQLITE_DROP_TEMP_TRIGGER 14 /* Trigger Name Table Name */ 15 #define SQLITE_DROP_TEMP_VIEW 15 /* View Name NULL */ 16 #define SQLITE_DROP_TRIGGER 16 /* Trigger Name Table Name */ 17 #define SQLITE_DROP_VIEW 17 /* View Name NULL */ 18 #define SQLITE_INSERT 18 /* Table Name NULL */ 19 #define SQLITE_PRAGMA 19 /* Pragma Name 1st arg or NULL */ 20 #define SQLITE_READ 20 /* Table Name Column Name */ 21 #define SQLITE_SELECT 21 /* NULL NULL */ 22 #define SQLITE_TRANSACTION 22 /* Operation NULL */ 23 #define SQLITE_UPDATE 23 /* Table Name Column Name */ 24 #define SQLITE_ATTACH 24 /* Filename NULL */ 25 #define SQLITE_DETACH 25 /* Database Name NULL */ 26 #define SQLITE_ALTER_TABLE 26 /* Database Name Table Name */ 27 #define SQLITE_REINDEX 27 /* Index Name NULL */ 28 #define SQLITE_ANALYZE 28 /* Table Name NULL */ 29 #define SQLITE_CREATE_VTABLE 29 /* Table Name Module Name */ 30 #define SQLITE_DROP_VTABLE 30 /* Table Name Module Name */ 31 #define SQLITE_FUNCTION 31 /* NULL Function Name */ 32 #define SQLITE_SAVEPOINT 32 /* Operation Savepoint Name */ 33 #define SQLITE_COPY 0 /* No longer used */ 34 #define SQLITE_RECURSIVE 33 /* NULL NULL */
View Code
z3是数据库、临时数据库等的名称。
z4是负责访问尝试的最内层的触发器或视图,如果为NULL,表示这种访问是这届来自顶级的SQL语句。
在实现authCallback()函数时,可通过判断事件代码op和z1、z2来控制对数据库的操作。
5、交互式程序相关API
SQLITE_API void sqlite3_interrupt(sqlite3*);
使给定连接上的数据库操作终止,并尽早返回。该程序在响应用户中断行为时调用,例如图形界面中的取消按钮或命令行中Ctrl+C调用此例程。
1 /* 2 ** This routine sets the progress callback for an Sqlite database to the 3 ** given callback function with the given argument. The progress callback will 4 ** be invoked every nOps opcodes. 5 */ 6 void sqlite3_progress_handler( 7 sqlite3 *db, 8 int nOps, 9 int (*xProgress)(void*), 10 void *pArg 11 )
该函数安装一个在sqlite3_exec()、sqlite3_step()和sqlite3_get_table()的回调函数。该函数目的是让应用在长时间运行的查询过程中为用户提供反馈信息。
如果进度回调函数返回非零值,将立即终止查询,任何更改将被回滚。如果查询较大事务,那么事务不会回滚,继续保持活动状态。此时,调用sqlite3_exec()将返回SQLITE_ABORT。
四、线程
不要尝试在UNIX平台系统调用fork()时,将连接传递给子进程,否则将无法工作。
1、共享缓存模型
允许一个进程中的多个连接使用共同的页缓存。该功能用于单个线程能够代表其他线程有效管理多个数据库连接的嵌入式服务器。
共享缓存模式中,实际的数据库连接存在于服务器线程中。应用线程通过某种机制向服务线程发送sql语句,服务器线程返回结果。
此模式下,数据库连接使用不同的并发模型和隔离级别。写数据库时,将不会影响读数据库;此时,读操作有可能看不到数据库背后的变化。
1)、读未提交隔离级别
如果将编译选项read_uncommitted设置为为true,连接不会在读取的表上加读锁。此时,另一个写操作可在连接读取的时候更改表。这可能导致不一致的查询结果,也意味着读取未提交模式中的连接既不阻止其他连接,也不会被其他连接阻止。
2)、解锁通知
1 SQLITE_API int sqlite3_unlock_notify( 2 sqlite3 *pBlocked, /* Waiting connection */ 3 void (*xNotify)(void **apArg, int nArg), /* Callback function to invoke */ 4 void *pNotifyArg /* Argument to pass to xNotify */ 5 );
代码因存在锁竞争失败而可能返回SQLITE_LOCKED,可调用sqlit3_unlock_notify()处理这种情况。
当sqlit3_unlock_notify()调用返回SQLITE_LOCKED时,说明存在死锁。需要进行回滚操作;当返回SQLITE_OK时,sqlite3_setp()等函数会阻塞,直到获取锁。
参考:https://blog.csdn.net/chinamming/article/details/17049913
2、线程与内存管理
SQLite有几个与线程和内存管理相关的函数,他们可指定堆大小、弹性堆栈限制,以及手动启动内存清理。
1 SQLITE_API sqlite3_int64 sqlite3_soft_heap_limit64(sqlite3_int64 N); 2 3 SQLITE_API SQLITE_DEPRECATED void sqlite3_soft_heap_limit(int N);
1 SQLITE_API int sqlite3_release_memory(int);
新程序应该使用sqlite3_soft_heap_limit64()函数,此函数将线程的当前堆设置为N字节,如果超过了N字节,将会自动调用sqlite3_release_memory(),返回值是实际释放的字节数。
使用上述API,需要在编译SQLite是启用预处理器指令SQLITE_ENABLE_MEMORY_MANAGEMENT,以启用内存管理。
转载于:https://www.cnblogs.com/mofei004/p/9397005.html
第六章 核心API (二)相关推荐
- Kali Linux 网络扫描秘籍 第六章 拒绝服务(二)
第六章 拒绝服务(二) 作者:Justin Hutchens 译者:飞龙 协议:CC BY-NC-SA 4.0 6.6 NTP 放大 DoS 攻击 NTP 放大 DoS 攻击利用响应远程 monlis ...
- 计算机组成原理第06章在线测试,计算机组成原理第六章单元测试(二)(含答案)(4页)-原创力文档...
PAGE PAGE 1 第六章单元测验 (二) 书生 1.用以指定待执行指令所在主存地址的寄存器是______.(单选) ????A.指令寄存器IR ????B.程序计数器PC ????C.存储器地址 ...
- 数据结构之KH[第五,六章] -->选择题 (二)
数据结构之KH[第五,六章] -->选择题 (二) 五.树和二叉树选择题 (1)把一棵树转换为二叉树后,这棵二叉树的形态是(A). A.唯一的 B.有多种 C.有多种,但根结点都没有左孩子 D. ...
- ggplot2读书笔记9:第六章 标度(二)
今天来学习第六章标度部分的最后一节~ 6.6 标度工具箱(Scales Toolbox) 除了调整标度的默认选项之外,你也可以重新创建新的标度,主要分为以下四类: 连续型位置标度:用于将整数.数值.日 ...
- python核心编程-第六章-个人笔记(二)
2019独角兽企业重金招聘Python工程师标准>>> 3.11.2 in操作符和index() 先看一段代码 >>> 'record' in music_med ...
- CakePHP 2.x CookBook 中文版 第六章 视图 之二
主题 主题可以使你快捷地切换页面的外观. 要使用主题,只需在控制器中指定主题名称: 1 class ExampleController extends AppController { 2 public ...
- 第六章 Java API
一.填空题 1.在Java中定义了3个类来封装对字符串的操作,他们分别是String.StringBuffer和StringBuilder. 2.Java中用于获取String字符串长度的方法是len ...
- 【MOOC】华中科技大学计算机组成原理慕课答案-第六章-中央处理器(二)
单选 1 (单选(2分)) 用以指定待执行指令所在主存地址的寄存器是______.(单选) √A. 程序计数器PC B. 指令寄存器IR C. 存储器地址寄存器MAR D. 数据缓冲寄存器 A. ...
- 鸟哥的Linux私房菜(基础篇)- 第二十六章、Linux 核心编译与管理
第二十六章.Linux核心编译与管理 最近升级日期:2009/09/18 我们说的 Linux 其实指的就是核心 (kernel) 而已.这个核心控制你主机的所有硬件并提供系统所有的功能,所以说,他重 ...
最新文章
- compser可以检查php扩展吗,composer扩展
- 树莓派python3_树莓派4没有python3怎么办
- 一文读懂全系列树莓派!
- c++ 哪些自定义的数据类型
- GIt本地相关操作(一)
- 微信卡券 - 微信公众平台 整理笔记
- 尽早查看针对Java 11的功能
- 浅谈测试rhel7新功能时的感受及遇到的问题
- 临时邮件、临时接收手机验证码等好用工具
- 关于Django下scv文件的基本操作
- LaTex写实验报告
- Amlogic S905X3外设驱动之RTC驱动:HYM8563驱动
- 2021-08-28-n皇后问题
- matlab英文字母对应数字,MATLAB编程:大写英文字母转换成数值(0-25)两种代码
- 2021年全球烤面包机收入大约1363.7百万美元,预计2028年达到1536.8百万美元
- 初探Java设计模式2:结构型模式(代理模式,适配器模式等)
- MicroStrategy(微策略)BI框架 iOS开发代码分享
- 使用IIS 5.0调整Web服务器的艺术与科学
- 当发请求时出现 401,原来可以这样解决,还不赶快学起来
- 《数据库技术原理与应用教程(第2版)》——导读