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.mzph.cn/news/748503.shtml

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

相关文章

栈队列数组试题(三)——栈和队列的应用

一、单项选择题 01.栈的应用不包括( ). A.递归 B.表达式求值 C.括号匹配 D.缓冲区 02&#xff0e;表达式a* (bc)-d的后缀表达式是()。 A. abcd*一 B. abc*d- C. abc*d- …

简单了解 vim 编辑器最基础的操作

简单了解 vim 编辑器最基础的操作 vim 这个是 Linux 上自带的一个文本编辑器&#xff0c;使用 vim 就可以更灵活的对文件进行编辑了&#xff08;虽然和记事本的定位差不多,实际上vim的使用要复杂很多&#xff09; 1.打开文件 语法&#xff1a;vim 文件名 示例&#xff1a;…

速盾:cdn是什么和作用有哪些

CDN, 也叫内容分发网络&#xff08;Content Delivery Network&#xff09;&#xff0c;是一种构建在分布式网络基础上的网络技术&#xff0c;旨在提高页面的访问速度和用户体验。CDN通过在全球各地部署服务器节点&#xff0c;并将网站的静态和动态内容复制到这些节点上&#xf…

16.旋转图像

给定一个 n n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。 你必须在 原地 旋转图像&#xff0c;这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。 示例 1&#xff1a; 输入&#xff1a;matrix [[1,2,3],[4,5,6],[7,8,9]] 输出&…

关于本地项目连接git远程仓库以及git设置ignore文件

一、本地项目如何连接git远程仓库 第一步&#xff0c; 首先我们在git上新建仓库。 第二步&#xff0c;打开本地项目文件夹&#xff0c;鼠标右键选择Git Bash Here 。 第三步&#xff0c;输入git init 命令&#xff08;在目录中创建新的 Git 仓库&#xff09;。 第四步&#xff…

Python强大的库和框架——NumPy

NumPy&#xff08;Numerical Python&#xff09;是一个用于科学计算的强大库&#xff0c;提供了支持大型、多维数组和矩阵的数据结构&#xff0c;以及用于处理这些数组的大量数学函数。 以下是关于 NumPy 的一些详解&#xff1a; 1. 安装 NumPy&#xff1a; 可以使用以下命令…

ubuntu 安装 infiniband 和 RoCE 驱动

下载驱动程序 驱动程序地址 https://network.nvidia.com/products/infiniband-drivers/linux/mlnx_ofed/ 安装 安装参考文档 https://docs.nvidia.com/networking/display/mlnxofedv24010331/installing+mlnx_ofed#src-2571322208_InstallingMLNX_OFED-InstallationProced…

BUGKU-WEB cookies

题目描述 题目截图如下&#xff1a; 进入场景看看&#xff1a; 解题思路 看源码看F12&#xff1a;看请求链接看提示&#xff1a;cookies欺骗 相关工具 插件&#xff1a;ModHeader或者hackbarbase64解密 解题步骤 看源码 就是rfrgrggggggoaihegfdiofi48ty598whrefeoia…

构建部署_Jenkins介绍与安装

构建部署_Jenkins介绍与安装 构建部署_Jenkins介绍与安装Jenkins介绍Jenkins安装 构建部署_Jenkins介绍与安装 Jenkins介绍 Jenkins是一个可扩展的持续集成引擎。 持续集成&#xff0c;就是通常所说的CI&#xff08;Continues Integration&#xff09;&#xff0c;可以说是现…

MySQL--深入理解MVCC机制原理

什么是MVCC&#xff1f; MVCC全称 Multi-Version Concurrency Control&#xff0c;即多版本并发控制&#xff0c;维持一个数据的多个版本&#xff0c;主要是为了提升数据库的并发访问性能&#xff0c;用更高性能的方式去处理数据库读写冲突问题&#xff0c;实现无锁并发。 什…

JUC之volatile关键字

Volatile 被volatile修饰的变量有两大特点&#xff1a;可见性与有序性 volatile的内存语义 volatile凭什么可以保证可见性和有序性&#xff1f;&#xff1f;&#xff1f;内存屏障 Memory Barrier 内存屏障 四大屏障 Volatile保证可见性、没有原子性&#xff0c;指令禁重…

手撕算法-对称二叉树

力扣101. 对称二叉树 链接 https://leetcode.cn/problems/symmetric-tree/description/ 题目描述 给你一个二叉树的根节点 root &#xff0c; 检查它是否轴对称。示例1&#xff1a;此树是对称的。示例2&#xff1a;此树也是对称的示例3&#xff1a;此树不对称 思路 一颗…

【WEEK3】学习目标及总结【SpringMVC】【中文版】

学习目标&#xff1a; 三周完成SpringMVC入门——第三周 感觉这周很难完成任务了&#xff0c;大概率还会有第四周 学习内容&#xff1a; 参考视频教程【狂神说Java】SpringMVC最新教程IDEA版通俗易懂数据处理JSON交互处理 学习时间及产出&#xff1a; 第三周 MON~FRI 2024.…

15 stack和queue的实现

栈和队列作为容器适配器,只需要将容器封装模板,传入什么容器用什么容器就好了 栈 #pragma oncetemplate <class T, class container vector<T>> class stack { public:void push(const T& x){_con.push_back(x);}void pop(){_con.pop_back();}T& top(){…

代码缺陷代价

目录 什么是语法缺陷什么是类型安全缺陷什么是内存和资源安全缺陷什么是并发安全缺陷什么是错误处理缺陷 什么是语法缺陷 语法缺陷是指程序中存在的语法错误或违反语法规则的问题。它通常是由于编程语言的语法规则不符合要求导致的。例如&#xff0c;缺少分号、括号不匹配、关…

peft模型微调--Prompt Tuning

模型微调&#xff08;Model Fine-Tuning&#xff09;是指在预训练模型的基础上&#xff0c;针对特定任务进行进一步的训练以优化模型性能的过程。预训练模型通常是在大规模数据集上通过无监督或自监督学习方法预先训练好的&#xff0c;具有捕捉语言或数据特征的强大能力。 PEF…

ubuntu(20.04)-安装JAVA环境-IDEA

1.下载IDEA 2.解压文件 sudo tar -zxvf idealC-2022.2.3.tar.gz -C /opt 3.添加环境变量&#xff1a; .vim ~/.bashrc export IDEA_HOME/opt/ideaIC-2022.2.3/ export PATH${IDEA_HOME}/bin:$PATH source ~/.bashrc 4.启动&#xff1a; cd /opt/ideaIC-2…

什么是SFP光模块?如何选择?

SFP光模块作为全球制造商和供应商的行业标准&#xff0c;至今仍被广泛使用。在许多网络中&#xff0c;如SONET、千兆以太网、光纤通道、PON和其他通信标准中&#xff0c;SFP光模块已经成为行业的中坚力量。本指南将为您介绍一些关于选择SFP模块的技巧。 什么是SFP光模块&#…

什么是浅拷贝和深拷贝

目录 一、概念 浅拷贝&#xff08;Shallow Copy&#xff09; 深拷贝&#xff08;Deep Copy&#xff09; 二、Java中使用工具来帮助进行对象的拷贝 ⭐三、bean工具类 总结 一、概念 当涉及到对象复制时&#xff0c;浅拷贝和深拷贝是两个重要的概念。它们描述了在复制对象…

Docker部署ChatGLM3、One API、FastGPT

创建并运行chatglm3容器 docker run --name chatglm3 -p 8000:8000 registry.cn-hangzhou.aliyuncs.com/ryyan/chatglm.cpp:chatglm3-q5_1 创建并运行one-api容器 (其中挂载路径 D:\one-api 可以选择你自己喜欢的目录) docker run --name oneapi -d -p 3000:3000 -e TZAsia…