SQLiteC/C++接口详细介绍之sqlite3类(三)

 快速跳转文章列表:SQLite—系列文章目录

上一篇:SQLiteC/C++接口详细介绍之sqlite3类(二)
 下一篇:SQLiteC/C++接口详细介绍之sqlite3类(四)

 6.sqlite3_create_module与sqlite3_create_module_v2函数

用于创建自定义SQLite模块。创建自定义模块可以让SQLite具有更高的灵活性并满足不同的需求,开发者可以使用该函数创建自己的模块创建自定义的SQL函数、聚合函数和虚拟表等功能。

要使用sqlite3_create_module_v2函数创建自定义模块,需要先定义一个sqlite3_module结构体,该结构体包含了自定义模块需要实现的一组回调函数。这些回调函数通过sqlite3_create_module_v2函数注册到SQLite数据库中。
如下2中格式

int sqlite3_create_module(sqlite3 *db,               /*SQLite数据库的句柄,用于指定该模块所属的数据库*/const char *zName,         /* 模块的名字,在SQLite数据库中必须唯一,用于描述该模块的作用和功能 */const sqlite3_module *p,   /* 自定义模块的结构体,包含了自定义模块需要实现的回调函数 */void *pClientData          /* 自定义的客户端数据指针,用于在回调函数中传递数据*/
);
int sqlite3_create_module_v2(sqlite3 *db,               /* SQLite数据库的句柄,用于指定该模块所属的数据库 */const char *zName,         /* 模块的名字,在SQLite数据库中必须唯一,用于描述该模块的作用和功能 */const sqlite3_module *p,   /*自定义模块的结构体,包含了自定义模块需要实现的回调函数*/void *pClientData,         /*自定义的客户端数据指针,用于在回调函数中传递数据 */void(*xDestroy)(void*)     /*模块销毁时候执行的自定义函数指针 */
);

两个函数返回值为整型,如果注册成功,返回 SQLITE_OK 表示成功,否则返回其他错误码,表示注册失败。一旦注册成功,该自定义模块就可以在SQLite数据库中使用了。

注意:

        sqlite3_create_module_v2函数最后一个参数xDestroy是可选的,用于指定自定义模块销毁时执行的函数指针。当该可选参数不为空时,SQLite数据库在销毁该模块时将调用该函数。在该函数中,开发者可以释放模块中使用的不再需要的内存、关闭打开的文件和句柄等清理工作。如果不需要执行销毁函数的操作,可以将 xDestroy 参数设置为NULL,在这种情况下,SQLite不会调用任何函数。在绝大多数情况下,xDestroy参数都被设置为NULL。

下面是一个简单的例子来说明如何使用sqlite3_create_module_v2来创建一个自定义SQLite模块以实现自定义的SQlite函数:

#include <sqlite3.h>
#include <stdio.h>
#include <stdlib.h>
// 自定义函数:计算两个整数之和
static void sumFunc(sqlite3_context *context, int argc, sqlite3_value **argv)
{if (argc == 2 && sqlite3_value_type(argv[0]) == SQLITE_INTEGER && sqlite3_value_type(argv[1]) == SQLITE_INTEGER) {sqlite3_int64 a = sqlite3_value_int64(argv[0]);sqlite3_int64 b = sqlite3_value_int64(argv[1]);sqlite3_int64 sum = a + b;sqlite3_result_int64(context, sum);} else {sqlite3_result_error(context, "Invalid arguments for sum function", -1);}
}
// 定义module结构体,注册自定义函数
static sqlite3_module myModule = {0, 0, 0, 0, 0, 0, 0,0,0,sumFunc};
int main(void)
{sqlite3 *db;char *errMsg;// 打开数据库if (sqlite3_open(":memory:", &db) != SQLITE_OK) {fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));sqlite3_close(db);exit(1);}// 注册自定义模块if (sqlite3_create_module_v2(db, "myfunc", &myModule, NULL, NULL) != SQLITE_OK) {fprintf(stderr, "Can't create module: %s\n", sqlite3_errmsg(db));sqlite3_close(db);exit(1);}// 测试自定义模块char *sql = "SELECT myfunc(1, 2)";if (sqlite3_exec(db, sql, NULL, NULL, &errMsg) != SQLITE_OK) {fprintf(stderr, "SQL error: %s\n", errMsg);sqlite3_free(errMsg);sqlite3_close(db);exit(1);}sqlite3_close(db);return 0;
}

在上面的例子中,我们首先实现了一个自定义函数 sumFunc,该函数可以计算两个整数的和。然后,我们定义了一个 myModule sqlite3_module 结构体,将自定义函数通过模块结构体注册到 SQLite 数据库中。

接下来,我们在程序中通过 sqlite3_open() 函数打开了一个内存数据库,并通过 sqlite3_create_module_v2() 函数将自定义模块注册到 SQLite 中。最后,我们使用sqlite3_exec()函数测试了自定义函数的功能,完成测试后关闭了 SQLite 数据库。

7.sqlite3_errstr类函数

        可以使用它来将 SQLite 中的错误码转换为相应的文本信息。当执行 SQLite 数据库的 C API 函数时,可能会出现各种错误,例如:SQL 语法错误、数据库不存在或文件打开失败等。此时,SQLite 数据库会返回一个错误码,用户可以使用 sqlite3_errstr() 函数将这个错误码转换为一个描述错误的对应信息。这种对 SQLite 错误码的转换可以帮助程序员快速了解错误所在,更方便地进行问题排查和处理。sqlite3_errstr() 此函数包含一个整形参数错误码,当传递到该函数的错误码是SQLite数据库中存在的错误码之一时,sqlite3_errstr() 返回该错误码的文本表示。否则,该函数返回 "unknown error" 的字符串。相关函数如下:

int sqlite3_errcode(sqlite3 *db);
int sqlite3_extended_errcode(sqlite3 *db);
const char *sqlite3_errmsg(sqlite3*);
const void *sqlite3_errmsg16(sqlite3*);
const char *sqlite3_errstr(int);
int sqlite3_error_offset(sqlite3 *db);

如果与数据库连接D关联的最新sqlite3_*API调用失败,则sqlite3_errcode(D)接口返回该数字结果代码或扩展结果代码API调用。sqlite3_extended_errcode()interface是相同的,只是它始终返回扩展结果代码,即使扩展结果代码是禁用。
sqlite3_errcode()和/或sqlite3_extended_errcode()可能会随着每次API调用而更改。除了,有些接口保证永远不会更改错误代码的值。保留错误代码接口包括:
sqlite3_errcode()
sqlite3_extended_errcode()
sqlite3_errmsg()
sqlite3_errmsg16()
sqlite3_error_offset()
sqlite3_errmsg()和sqlite3_errmsg16()返回英语描述错误的文本,分别为UTF-8或UTF-16,如果没有可用的错误消息,则为NULL。(请参阅SQLite如何处理无效的UTF,了解此规则的例外情况。用于保存错误消息字符串的内存在内部进行管理。应用程序无需担心释放结果。但是,错误字符串可能会被覆盖或解除分配对其他SQLite接口函数的后续调用。
sqlite3_errstr(E)接口返回英文文本将结果代码E描述为UTF-8,如果E不是文本错误消息可用的结果代码。用于保存错误消息字符串的内存在内部进行管理并且不得由应用程序释放。
如果最近的错误引用了输入中的特定标记SQL,sqlite3_error_offset()接口返回字节偏移量该令牌的开头。返回的字节偏移量sqlite3_error_offset()假定输入SQL为UTF8。如果最近的错误未引用输入中的特定标记SQL,则sqlite3_error_offset()函数返回-1。
当使用序列化线程模式时,它可能是如果在两者之间的单独线程上发生第二个错误第一个错误的时间和对这些接口的调用。发生这种情况时,将报告第二个错误,因为这些接口始终报告最新结果。避免这样一来,每个线程都可以获得数据库连接D的独占使用通过在开始之前调用sqlite3_mutex_enter(sqlite3_db_mutex(D))使用D并在之后调用sqlite3_mutex_leave(sqlite3_db_mutex(D))对此处列出的接口的所有调用均已完成。
如果接口出现故障并SQLITE_MISUSE,则表示接口被应用程序错误地调用。在这种情况下,可以设置错误代码和消息,也可以不设置错误代码和消息。 

8.sqlite3_prepare类函数

是SQLite C API中用于编译和准备SQL语句的函数之一。使用sqlite3prepare函数可以将一个SQL字符串编译成SQLite内部认识的字节码,该字节码包含了该SQL语句执行的计划。如果该SQL语句后面有参数,那么sqlite3prepare函数会使用占位符代替它们,并返回一个sqlite3stmt类型的指针,该指针可以用于为SQL语句绑定参数、执行SQL语句和获取语句执行的结果。

相关函数:

int sqlite3_prepare(sqlite3 *db,            /* 数据库句柄 */const char *zSql,       /* SQL语句,UTF-8编码 */int nByte,              /* zSql的最大长度,以字节为单位 */sqlite3_stmt **ppStmt,  /* 输出:语句句柄 */const char **pzTail     /* 输出:zSql未使用的部分的指针 */
);
int sqlite3_prepare_v2(sqlite3 *db,            /* 数据库句柄 */const char *zSql,       /* SQL语句,UTF-8编码 */int nByte,              /* zSql的最大长度,以字节为单位 */sqlite3_stmt **ppStmt,  /* 输出:语句句柄 */const char **pzTail     /* 输出:zSql未使用的部分的指针 */
);
int sqlite3_prepare_v3(sqlite3 *db,            /* 数据库句柄 */const char *zSql,       /* SQL语句,UTF-8编码 */int nByte,              /* zSql的最大长度,以字节为单位 */unsigned int prepFlags, /* 零个或多个SQLITE_PREPARE_标志 */sqlite3_stmt **ppStmt,  /* 输出:语句句柄 */const char **pzTail     /* 输出:zSql未使用的部分的指针 */
);
int sqlite3_prepare16(sqlite3 *db,            /* 数据库句柄 */const void *zSql,       /* SQL语句,UTF-16编码 */int nByte,              /* zSql的最大长度,以字节为单位 */sqlite3_stmt **ppStmt,  /* 输出:语句句柄 */const void **pzTail     /* 输出:zSql未使用的部分的指针 */
);
int sqlite3_prepare16_v2(sqlite3 *db,            /* 数据库句柄 */const void *zSql,       /* SQL语句,UTF-16编码 */int nByte,              /* zSql的最大长度,以字节为单位 */sqlite3_stmt **ppStmt,  /* 输出:语句句柄 */const void **pzTail     /* 输出:zSql未使用的部分的指针 */
);
int sqlite3_prepare16_v3(sqlite3 *db,            /* 数据库句柄 */const void *zSql,       /* SQL语句,UTF-16编码 */int nByte,              /* zSql的最大长度,以字节为单位 */unsigned int prepFlags, /* 零个或多个SQLITE_PREPARE_标志 */sqlite3_stmt **ppStmt,  /* 输出:语句句柄 */const void **pzTail     /* 输出:zSql未使用的部分的指针 */
);

上述函数均用于准备 SQL 语句并将其编译成可执行的字节码。其中:

- 参数 db 是数据库连接句柄。
- 参数 zSql 是要编译的 SQL 语句,可以是 UTF-8 或 UTF-16 编码。
- 参数 nByte 是 SQL 语句的最大长度,以字节为单位。
- 参数 ppStmt 是输出参数,该函数将编译后的语句句柄存储在该指针中。
- 参数 pzTail 是输出参数,该函数将指向未使用的 SQL 语句部分的指针存储在该指针中。

sqlite3_prepare_v3和sqlite3_prepare16_v3函数带有一个额外的参数,即零个或多个SQLITE_PREPARE_标志,可以控制语句如何被准备和编译。

函数返回 SQLITE_OK 表示成功,否则返回其他错误码。

说明:

要执行SQL语句,必须首先将其编译为字节码使用这些例程之一进行编程。或者,换句话说,这些例程是预准备语句对象的构造函数。
首选例程是sqlite3_prepare_v2()。sqlite3_prepare()接口是遗留的,应避免使用。sqlite3_prepare_v3()有一个额外的“prepFlags”选项,用于用于特殊目的。
首选使用UTF-8接口,因为目前是SQLite使用UTF-8进行所有解析。提供UTF-16接口为了方便起见。UTF-16接口的工作原理是将将文本输入到UTF-8中,然后调用相应的UTF-8接口。
第一个参数“db”是从之前成功调用sqlite3_open()、sqlite3_open_v2()或sqlite3_open16()。数据库连接不得已关闭。
第二个参数“zSql”是要编译、编码的语句作为UTF-8或UTF-16。sqlite3_prepare()、sqlite3_prepare_v2()、和sqlite3_prepare_v3()接口使用UTF-8和sqlite3_prepare16()、sqlite3_prepare16_v2()、和sqlite3_prepare16_v3()使用UTF-16。
如果nByte参数为负数,则zSql将读取到第一个零终结者。如果nByte为正数,则它是从zSql读取的字节数。如果nByte为零,则没有准备语句生成。如果调用方知道提供的字符串是nul终止的,则传递一个nByte参数有一个很小的性能优势,即是输入字符串中的字节数,包括NUL终止符。
如果pzTail不为NULL,则*pzTail指向第一个字节过了zSql中第一个SQL语句的末尾。仅限这些例程编译zSql中的第一个语句,因此*pzTail指向什么仍未编译。
*ppStmt指向已编译的预准备语句,该语句可以是使用sqlite3_step()执行。如果出现错误,则设置*ppStmt设置为NULL。如果输入文本不包含SQL(如果输入为空string或注释),则*ppStmt设置为NULL。调用过程负责删除已编译的SQL语句在完成后使用sqlite3_finalize()。ppStmt不能为NULL。
成功后,sqlite3_prepare()系列例程返回SQLITE_OK;否则返回错误代码。
sqlite3_prepare_v2()、sqlite3_prepare_v3()、sqlite3_prepare16_v2()、和sqlite3_prepare16_v3()接口建议用于所有新程序。较旧的接口(sqlite3_prepare()和sqlite3_prepare16())为了向后兼容而保留,但不建议使用它们。在“vX”接口中,预准备语句返回的(sqlite3_stmt对象)包含原始SQL文本。这会导致sqlite3_step()接口在三种方式上表现不同:
如果数据库架构发生更改,而不是按原样返回SQLITE_SCHEMA总是用来做,sqlite3_step()会自动重新编译SQL语句,然后尝试再次运行它。在sqlite3_step()放弃并返回错误之前,将发生多达SQLITE_MAX_SCHEMA_RETRY次重试。
发生错误时,sqlite3_step()将返回详细的错误代码或扩展错误代码之一。遗留行为是sqlite3_step()只会返回泛型SQLITE_ERROR结果代码应用程序必须再次调用sqlite3_reset()才能找到问题的根本原因。使用“v2”准备接口,则会立即返回错误的根本原因。
如果特定值绑定到host参数WHERE子句可能会影响语句的查询计划选择,然后语句将自动重新编译,就好像曾经有过一样架构更改,在进行任何更改后的第一个sqlite3_step()调用时添加到该参数的绑定中。WHERE子句参数的特定值可能会影响如果参数是LIKE或GLOB运算符的左侧,或者将参数与索引列进行比较,则选择查询计划并启用SQLITE_ENABLE_STAT4编译时选项。
sqlite3_prepare_v3()与sqlite3_prepare_v2()的不同之处仅在于具有额外的prepFlags参数,它是一个由零或更多SQLITE_PREPARE_*标志。这sqlite3_prepare_v2()接口的工作原理与sqlite3_prepare_v3()的prepFlags参数为零。
上述函数均用于准备SQL语句并将其编译成可执行的字节码。其中:
-参数db是数据库连接句柄。
-参数zSql是要编译的SQL语句,可以是UTF-8或UTF-16编码。
-参数nByte是SQL语句的最大长度,以字节为单位。
-参数ppStmt是输出参数,该函数将编译后的语句句柄存储在该指针中。
-参数pzTail是输出参数,该函数将指向未使用的SQL语句部分的指针存储在该指针中。
sqlite3_prepare_v3和sqlite3_prepare16_v3函数带有一个额外的参数,即零个或多个SQLITE_PREPARE_标志,可以控制语句如何被准备和编译。
函数返回SQLITE_OK表示成功,否则返回其他错误码。

参考文献:

1. C-language Interface Specification for SQLite官方说明文档

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/276844.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据库不应放在容器中?- B站Kubernetes有状态服务实践(Elasticsearch/Clickhouse)

本期作者 前言 云原生时代下&#xff0c; Kubernetes已成为容器技术的事实标准&#xff0c; 使得基础设施领域应用下自动化运维管理与编排成为可能。对于无状态服务而言&#xff0c; 业界早已落地数套成熟且较完美的解决方案。可对于有状态的服务&#xff0c; 方案的复杂度就以…

电视盒子解析安装包失败,安卓4.4安装不了kodi的解决方法,如何安装kodi

有些安卓电视或者电视盒子的安卓系统版本太低、自身架构或者屏蔽了安装其他应用的功能&#xff0c;下载的Kodi apk安装包提示无法安装&#xff0c;解析程序包时出现问题、解析出错无法安装、[INSTALL_FAILED_OLDER_SDK]、此应用与您的电视不兼容。 解决方法&#xff1a; 1、3…

学习Android的第二十八天

目录 Android Service (服务) 线程 Service (服务) Service 相关方法 Android 非绑定 Service startService() 启动 Service 验证 startService() 启动 Service 的调用顺序 Android 绑定 Service bindService() 启动 Service 验证 BindService 启动 Service 的顺序 …

【AI】如何创建自己的自定义ChatGPT

如何创建自己的自定义ChatGPT 目录 如何创建自己的自定义ChatGPT大型语言模型(LLM)GPT模型ChatGPTOpenAI APILlamaIndexLangChain参考推荐超级课程: Docker快速入门到精通Kubernetes入门到大师通关课本文将记录如何使用OpenAI GPT-3.5模型、LlamaIndex和LangChain创建自己的…

DirectShowPlayerService::doSetUrlSource: Unresolved error code 0x800c000d

报出这个问题&#xff0c;应该是对给的url解析不正确&#xff0c;我给的是rtsp的视频流地址&#xff0c;应该是对该格式解析异常。 所以参考两篇文&#xff1a; QT无法播放视频&#xff1a;报错&#xff1a;DirectShowPlayerService::doRender: Unresolved error code 0x8004…

vue3项目随笔1

1,Eslint Prettier 报错情况&#xff1a; 解决办法&#xff1a; &#xff08;1&#xff09;下载Prettier - code formatter &#xff08;2&#xff09;配置setting.json文件 文件 -> 首选项 -> 设置 -> 用户 -> Eslint "editor.defaultFormatter":…

拖动排序与置顶的Java实现

文章目录 1、需求分析2、表设计3、接口设计4、业务层5、数据层 整理个需求的实现思路。 1、需求分析 列表展示了一系列产品&#xff0c;现要支持通过拖动来给产品排序&#xff0c;也要支持单个产品的置顶、删除。类似CSDN的专栏文章管理。 2、表设计 现要支持对列表的产品进…

融入Facebook的世界:探索数字化社交的魅力

融入Facebook的世界&#xff0c;是一场数字化社交的奇妙之旅。在这个广袤的虚拟社交空间中&#xff0c;人们可以尽情展现自己、分享生活&#xff0c;与全球朋友、家人和同事保持紧密联系&#xff0c;共同探索社交互动的乐趣与魅力。让我们深入了解这个世界的魅力所在&#xff1…

ASP.NET-Server.HtmlEncode

目录 背景: 1.转义特殊字符&#xff1a; 2.防止跨站脚本攻击&#xff08;XSS&#xff09;&#xff1a; 3.确保输出安全性&#xff1a; 4.保留原始文本形式&#xff1a; 5.与用户输入交互安全&#xff1a; 实例说明: 不用Server.HtmlEncode 效果展示: 用Server.HtmlEnc…

多场成像,快速提高机器视觉检测能力--51camera

多阵列CMOS传感器与芯片级涂层二向色滤光片相结合&#xff0c;可在单次扫描中同时捕获明场、暗场和背光图像。 多场成像是一种新的成像技术&#xff0c;它可以在不同的光照条件下同时捕获多幅图像。再加上时间延迟积分(TDI)&#xff0c;这种新兴的成像技术可以克服许多限制的传…

【敬伟ps教程】视频动画

文章目录 视频文档视频时间轴帧动画视频文档 工作区需由[基本功能]切换为[动感] 可以看到我们需从时间的维度来编辑动态视觉图像 时间轴:从时间的维度来编辑动态视觉图像 PS提供的时间轴有两种:1、视频时间轴;2、动画时间轴 新建视频文档,点击新建或Ctrl+N,预设选择“胶…

springboot276基于JS的个人云盘管理系统的设计与实现

个人云盘管理系统设计与实现 摘 要 传统办法管理信息首先需要花费的时间比较多&#xff0c;其次数据出错率比较高&#xff0c;而且对错误的数据进行更改也比较困难&#xff0c;最后&#xff0c;检索数据费事费力。因此&#xff0c;在计算机上安装个人云盘管理系统软件来发挥其…

3.自定义工程目录配置CMakeLists

问题背景 熟悉stm32keil开发的都知道&#xff0c;我们在编写不同的外设时&#xff0c;通常都会单独编写一个app文件夹或者是user文件夹之类的来存放不同外设功能的源文件和头文件。 在前面一节2.构建第一个工程并烧录到ESP32开发板-CSDN博客中&#xff0c;我们是使用了一个乐鑫…

【联邦学习贡献评估-参与方贡献评估方案的介绍】

在明确如何度量参与方组合数据价值的基础上, 本篇介绍如何进一步度量参与方在联邦合作中的贡献, 具体介绍如下 4 种参与方贡献评估方案. 个体法 将参与方自身数据的价值度量或者相关变体作为该参与方的贡献. 个体法可以基于任何 数据价值度量指标进行, 特别地, 有个体信誉、个…

Python面试笔记

Python面试笔记 PythonQ. Python中可变数据类型与不可变数据类型&#xff0c;浅拷贝与深拷贝详解Q. 解释什么是lambda函数&#xff1f;它有什么好处&#xff1f;Q. 什么是装饰器&#xff1f;Q. 什么是Python的垃圾回收机制&#xff1f;Q. Python内置函数dir的用法&#xff1f;Q…

SpringBoot整合Activiti7——实战之请假流程(普通)

文章目录 代码实现xml文件部署流程启动流程查询任务填写请假单部门审批 请假流程&#xff1a;开始-填写请假单-部门审批-结束 代码实现 xml文件 <?xml version"1.0" encoding"UTF-8"?> <definitions xmlns"http://www.omg.org/spec/BPMN/…

服务器段的连接端口和监听端口编程实现

new ServerSocket(int)是开启监听端口&#xff0c;并不是连接端口。真正的连接端口是随机开辟的空闲端口&#xff0c;当连接创建完成后&#xff0c;监听关口可以继续等待下一次连接请求&#xff0c;处于空闲等待状态。 编程实现方式 1 、主线程一直处于阻塞等待状态&#xff0c…

编程高级陷阱-破坏原有生态

今天聊点有意思的&#xff0c;昨天写了一个链表翻转&#xff0c;说一说里面大家会遇到的坑&#xff0c;具体可以看 教你三指针拿捏链表翻转-CSDN博客 有这样一个场景&#xff0c;给你一个单链表的头节点 head &#xff0c;请你判断该链表是否为回文链表。如果是&#xff0c;返回…

汇总全网免费API,持续更新(新闻api、每日一言api、音乐。。。)

Public&FreeAPI 网址&#xff1a;apis.whyta.cn &#xff08;推荐&#xff09; UomgAPI 网址&#xff1a;https://api.uomg.com 教书先生 网址&#xff1a;https://api.oioweb.cn/ 山海API https://api.shserve.cn/ 云析API铺 https://api.a20safe.com/ 韩小韩…

提交数据加快百度搜索引擎收录

百度站长工具做了更新&#xff0c;百度收录的地址分享如下&#xff0c;新站点提交后&#xff0c;可以加快百度收录。 普通收录_加快网站内容抓取&#xff0c;快速提交数据工具_站长工具_网站支持_百度搜索资源平台普通收录工具可实时向百度推送数据&#xff0c;创建并提交site…