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

news2024/11/25 16:25:48
上一篇: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.coloradmin.cn/o/1511975.html

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

相关文章

ChatGPT无法登录,提示我们检测到可疑的登录行为,将阻止进一步的尝试。请与管理员联系

1. 问题描述 之前本来已经连续稳定使用ChatGPT好几个月了&#xff0c;但是今天尝试登录ChatGPT的时候&#xff0c;却提示&#xff1a;我们检测到可疑的登录行为&#xff0c;将阻止进一步的尝试。请与管理员联系。 此外&#xff0c;我还在网上看到了一些相关的消息&#xff0c;…

Kafka的基本介绍以及扩展

文章目录 基本操作新增Topic查询Topic修改Topic删除Topic 生产者和消费者创建生产者创建消费者 Broker扩展Producer扩展Topic、Partition、Message扩展存储策略容错机制 基本操作 新增Topic 指定两个分区&#xff0c;两个副本&#xff0c;replication不能大于集群中的broker数…

HarmonyOS预览功能报错:[webpack-cli] SyntaxError: Unexpected end of JSON input

harmonyos预览功能报错 在使用DevEco Studio写页面&#xff0c;进行预览的时候报错&#xff1a; [Compile Result] [webpack-cli] SyntaxError: Unexpected end of JSON input [Compile Result] at JSON.parse (<anonymous>) [Compile Result] at updateCached…

Fair Data Exchange:区块链实现的原子式公平数据交换

1. 引言 2024年斯坦福大学和a16z crypto research团队 论文 Atomic and Fair Data Exchange via Blockchain 中&#xff0c;概述了一种构建&#xff08;包含过期EIP-4844 blobs的&#xff09;fair data-markets的协议。该论文源自a16z crypto的暑期实习计划&#xff0c;与四名…

第四弹:Flutter图形渲染性能

目标&#xff1a; 1&#xff09;Flutter图形渲染性能能够媲美原生&#xff1f; 2&#xff09;Flutter性能优于React Native? 一、Flutter图形渲染原理 1.1 Flutter图形渲染原理 Flutter直接调用Skia 1&#xff09;Flutter将一帧录制成SkPicture&#xff08;skp&#xff…

2023 收入最高的十大编程语言

本期共享的是 —— 地球上目前已知超过 200 种可用的编程语言&#xff0c;了解哪些语言在 2023 为开发者提供更高的薪水至关重要。 过去一年里&#xff0c;我分析了来自地球各地超过 1000 万个开发职位空缺&#xff0c;辅助我们了解市场&#xff0c;以及人气最高和收入最高的语…

判断对象是否可以被回收:引用计数法,可达性分析,finalize()判定

引用计数法 对象每次被赋值给变量时&#xff0c;该对象的计数1&#xff0c; 若将该变量置为null,则该对象的计数-1 若该对象的计数器为0 &#xff0c;则该对象就会判定为垃圾对象 可达性分析 遍历内存中的所有变量&#xff0c;静态变量&#xff0c;然后将该变量当作GCroot根…

安装配置HBase

HBase集群需要整个集群所有节点安装的HBase版本保持一致&#xff0c;并且拥有相同的配置&#xff0c;具体配置步骤如下&#xff1a; 1. 解压缩HBase的压缩包 2. 配置HBase的环境变量 3. 修改HBase的配置文件&#xff0c;HBase的配置文件存放在HBase安装目录下的conf中 4. 首…

在没有推出硬盘的情况下,重启mac电脑,外接移动硬盘无法加载显示?

一、mac磁盘工具显示未装载 1.打开终端&#xff0c;输入 diskutil list查看当前硬盘列表&#xff0c;大多数时候&#xff0c;可以解决。 二、使用命令行装载硬盘 执行上面命令后&#xff0c;仍不起作用&#xff0c;则手动挂载&#xff0c;在命令行输入如下内容&#xff1a; …

数学建模理论与实践国防科大版

目录 1.数学建模概论 2.生活中的数学建模 2.1.行走步长问题 2.2.雨中行走问题 2.3.抽奖策略 2.4.《非诚勿扰》女生的“最优选择” 3.集体决策模型 3.1.简单多数规则 3.2.Borda数规则 3.3.群体决策模型公理和阿罗定理 1.数学建模概论 1.数学模型的概念 2.数学建模的概…

WAServiceMainContext.js:2 ReferenceError: result is not defined

WAServiceMainContext.js:2 ReferenceError: result is not defined at success (index.js? [sm]:280) at Function.forEach.u.<computed> (WASubContext.js?twechat&s1710205354985&v2.16.1:2) at :22955/appservice/<api request success callback fun…

最好用的流程编辑器bpmn-js系列之基本使用

BPMN&#xff08;Business Process Modeling Notation&#xff09;是由业务流程管理倡议组织BPMI&#xff08;The Business Process Management Initiative&#xff09;开发的一套标准的业务流程建模符号规范。其目的是为用户提供一套容易理解的标准符号&#xff0c;这些符号作…

Android audiotrack尾帧无声

前言 产品一直有用户反馈音频截断问题。在机遇巧合下现学现卖音频知识处理相关问题。 问题描述 我们查看以下简化播放器代码&#xff1a; class AACPlayer(private val filePath: String) {private val TAG "AACPlayer"private var extractor: MediaExtractor? …

nRF52832——串口 UART 和 UARTE 外设应用

nRF52832——串口 UART 和 UARTE 外设应用 UART 和 UARTE 原理UART 功能描述UARTE 功能介绍 应用实例串口打印实例串口输入与回环UART 模式串口中断 UART 和 UARTE 原理 UART 功能描述 串口 UART 也称为通用异步收发器。是各种处理器中常用的通信接口&#xff0c;在 nRF52 芯…

微信小程序实现上下手势滑动切换

效果图 思路 实现一个微信小程序的复合滚动页面&#xff0c;主要通过Swiper组件实现垂直方向的轮播功能&#xff0c;每个轮播项内部使用Scroll-View组件来展示可垂直滚动的长内容&#xff0c;如图片和文本。 代码 <!-- wxml --> <view class"swiper-container…

Spring Boot+Vue前后端分离项目如何部署到服务器

&#x1f31f; 前言 欢迎来到我的技术小宇宙&#xff01;&#x1f30c; 这里不仅是我记录技术点滴的后花园&#xff0c;也是我分享学习心得和项目经验的乐园。&#x1f4da; 无论你是技术小白还是资深大牛&#xff0c;这里总有一些内容能触动你的好奇心。&#x1f50d; &#x…

搜索引擎SEO策略介绍

baidu搜索&#xff1a;如何联系八爪鱼SEO baidu搜索&#xff1a;如何联系八爪鱼SEO baidu搜索&#xff1a;如何联系八爪鱼SEO 第一、 关键词的选择策略&#xff1a; 1、门户类的网站关键词选择策略&#xff1a; 网站每个页面本身基本都包含有关键词&#xff1a;网站拥有上百…

STM32-PWR电源控制

PWR(Power Control)电源控制 管理STM32内部的电源供电部分&#xff0c;可以实现可编程电压检测器和低功耗模式的功能。 电源管理器 上电复位&#xff08;POR&#xff09;和掉电复位&#xff08;PDR&#xff09; STM32内部有一个完整的上电复位(POR)和掉电复位(PDR)电路&…

免费搭建导航网站教程带免费空间域名源码

使用免费空间和免费域名免费搭建一个导航网站 手把手视频教程 https://pan.xunlei.com/s/VNsoMehs7RCjz3IClV6h2vNMA1?pwdq596#

【阿里云系列】-部署ACK集群的POD应用日志如何集成到日志服务(SLS)中

介绍 我们在实际部署应用到阿里云的ACK集群后&#xff0c;由于后期应用服务的持续维护诉求可能需要跟踪排查问题&#xff0c;此时就要具备将应用的历史日志存档便于后期排查问题 处理方式 为了解决以上的普遍需求&#xff0c;需要将ACK中的应用日志采集到SLS的Logstore中,然…