SQLite运行时可加载扩展(三十五)

返回:SQLite—系列文章目录   

上一篇:SQLite轻量级会话扩展(三十四)

下一篇:SQLite的DBSTAT 虚拟表(三十六)

1. 概述

SQLite 能够在运行时加载扩展(包括新的应用程序定义的 SQL 函数、整理序列、虚拟表和 VFS)。 此功能允许开发扩展代码和 与应用程序分开测试,然后加载 根据需要。

扩展也可以与应用程序静态链接。 下面显示的代码模板将像静态一样工作 链接扩展,因为它作为运行时可加载扩展,除了 您应该提供入口点函数 (“sqlite3_extension_init”) 如果应用程序包含以下内容,则使用其他名称以避免名称冲突 两个或多个扩展。

2. 加载扩展

SQLite 扩展是共享库或 DLL。要加载它,您需要 需要向 SQLite 提供包含 共享库或 DLL 以及用于初始化扩展的入口点。 在 C 代码中,此信息是使用 sqlite3_load_extension() API 提供的。请参阅有关此内容的文档 例程以获取更多信息。

请注意,不同的操作系统使用不同的文件名 其共享库的后缀。Windows 使用“.dll”,Mac 使用 “.dylib”,除 Mac 外的大多数 Unix 都使用“.so”。如果你想 使你的代码可移植,你可以从共享中省略后缀 将自动添加库文件名和相应的后缀 通过 sqlite3_load_extension() 接口。

还有一个可用于加载扩展的 SQL 函数:load_extension(X,Y)。它的工作方式与 sqlite3_load_extension() C 接口类似。

加载扩展的两种方法都允许您指定 扩展的入口点的名称。 您可以将此参数留空 - 传入 sqlite3_load_extension() C 语言接口的 NULL 指针 或省略 load_extension() SQL 接口的第二个参数 - 扩展加载器逻辑将尝试找出入口点 靠它自己。它将首先尝试通用扩展名 “sqlite3_extension_init”。如果这不起作用,它会构造一个 使用模板“sqlite3_X_init”的入口点,其中 X 被替换 与文件名中每个 ASCII 字符的小写等效值 在最后一个“/”之后和第一个“.”之前省略 前三个字符(如果它们恰好是“lib”)。因此,例如, 如果文件名为“/usr/lib/libmathfunc-4.8.so”,则为入口点名称 将是“sqlite3_mathfunc_init”。或者,如果文件名是 “./SpellFixExt.dll”,则将调用入口点 “sqlite3_spellfixext_init”。

出于安全原因,扩展加载默认处于关闭状态。 为了使用 C 语言或 SQL 扩展加载函数, 必须首先使用

​ sqlite3_db_config(db,SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION,1,NULL)

启用扩展加载 应用程序中的 C 语言 API。

在命令行 shell 中,可以使用 “.load” 点命令。例如:

.load ./YourCode

请注意,命令行 shell 程序已启用 扩展加载(通过调用 sqlite3_enable_load_extension() 接口作为其设置的一部分),因此上面的命令无需 任何特殊开关、设置或其他复杂情况。

带有一个参数的“.load”命令调用 sqlite3_load_extension() 将 zProc 参数设置为 NULL,导致 SQLite 首先查找 名为“sqlite3_extension_init”,然后名为“sqlite3_X_init”的入口点 其中“X”派生自文件名。如果扩展有条目 点与不同的名称,只需提供该名称作为第二个 论点。例如:

.load ./YourCode nonstandard_entry_point

3. 编译可加载扩展

可加载的扩展是 C 代码。要编译它们,请执行以下操作 最像 UNIX 的操作 系统,通常的命令是这样的:

gcc -g -fPIC -shared YourCode.c -o YourCode.so

Mac 是类似 unix 的,但它们不遵循通常的共享库 约定。要在 Mac 上编译共享库,请使用类似 这:

gcc -g -fPIC -dynamiclib YourCode.c -o YourCode.dylib

如果在尝试加载库时收到错误消息 这说“Mach-O,但架构错误”,那么您可能需要添加 命令行选项“-arch i386”或“arch x86_64”到 gcc,具体取决于 关于如何构建应用程序。

若要使用 MSVC 在 Windows 上编译,请使用类似于以下内容的命令 通常可以:

cl YourCode.c -link -dll -out:YourCode.dll

要使用 MinGW 为 Windows 编译,命令行就像它一样 适用于 UNIX,但输出文件后缀更改为“.dll”,并且 省略了 -fPIC 参数:

gcc -g -shared YourCode.c -o YourCode.dll

4. 对可加载扩展进行编程

模板可加载扩展包含以下三个元素:

  1. 使用源顶部的“#include < sqlite3ext.h>” 代码文件,而不是“#include < sqlite3.h>”。

  2. 将宏“SQLITE_EXTENSION_INIT1”单独放在一行上 紧接在“#include < sqlite3ext.h>”行之后。

  3. 添加一个扩展加载入口点例程,如下所示 内容如下:

    #ifdef _WIN32
    __declspec(dllexport)
    #endif
    int sqlite3_extension_init( /* <== Change this name, maybe */sqlite3 *db, char **pzErrMsg, const sqlite3_api_routines *pApi
    ){int rc = SQLITE_OK;SQLITE_EXTENSION_INIT2(pApi);/* insert code to initialize your extension here */return rc;
    }

    您可以很好地将入口点的名称自定义为 对应于您将要生成的共享库的名称, 而不是使用通用的“sqlite3_extension_init”名称。给 您的扩展自定义入口点名称将使您能够静态地 在没有链接器的情况下将两个或多个扩展链接到同一程序中 冲突(如果您以后决定使用静态链接而不是运行时) 连接。 如果您的共享库最终被命名为“YourCode.so”或 编译器示例中显示的“YourCode.dll”或“YourCode.dylib” ,那么正确的入口点名称将是 “sqlite3_yourcode_init”。

这是一个完整的模板扩展,您可以复制/粘贴 要开始使用,请执行以下操作:

/* Add your header comment here */
#include <sqlite3ext.h> /* Do not use <sqlite3.h>! */
SQLITE_EXTENSION_INIT1/* Insert your extension code here */#ifdef _WIN32
__declspec(dllexport)
#endif
/* TODO: Change the entry point name so that "extension" is replaced by
** text derived from the shared library filename as follows:  Copy every
** ASCII alphabetic character from the filename after the last "/" through
** the next following ".", converting each character to lowercase, and
** discarding the first three characters if they are "lib".
*/
int sqlite3_extension_init(sqlite3 *db, char **pzErrMsg, const sqlite3_api_routines *pApi
){int rc = SQLITE_OK;SQLITE_EXTENSION_INIT2(pApi);/* Insert here calls to**     sqlite3_create_function_v2(),**     sqlite3_create_collation_v2(),**     sqlite3_create_module_v2(), and/or**     sqlite3_vfs_register()** to register the new features that your extension adds.*/return rc;
}

4.1. 示例扩展

完整且可加载扩展的许多示例可以是 在 ext/misc 子目录的 SQLite 源代码树中看到。 该目录中的每个文件都是一个单独的扩展名。文档 由文件上的标题注释提供。 以下是对 ext/misc 子目录:

  • 卡雷.c — carray 表值函数的实现。

  • 压缩.c — 实现应用程序定义的 SQL 函数 compress()和 uncompress()对文本或 blob 内容进行 zLib 压缩。

  • json1.c — JSON SQL 函数和表值函数的实现。 这是一个更大、更复杂的扩展。

  • memvfs.c — 实现将所有内容存储在内存中的新 VFS。

  • rot13.c — rot13() SQL 函数的实现。这是一个非常简单的扩展函数示例 并可用作创建新扩展的模板。

  • 系列.c — 实现generate_series虚拟表和表值函数。这是一个相对简单的示例 虚拟表实现,可以作为编写模板 新的虚拟表。

其他更复杂的扩展可以在子文件夹中找到 在 ext/ 下,除 ext/misc/ 外。

5. 持久可加载扩展

可加载扩展的默认行为是卸载它 当最初调用 sqlite3_load_extension() 的数据库连接关闭时,从进程内存中。(换言之,xDlClose 方法 的 sqlite3_vfs 对象在数据库时为所有扩展调用 连接关闭。但是,如果初始化过程返回 SQLITE_OK_LOAD_PERMANENTLY 而不是 SQLITE_OK,则扩展将 未卸载(不会调用 xDlClose),并且扩展将保留 无限期地在进程内存中。SQLITE_OK_LOAD_PERMANENTLY回归 value 对于想要注册新 VFS 的扩展非常有用。

澄清一下:初始化函数返回的扩展 SQLITE_OK_LOAD_PERMANENTLY在数据库之后继续存在于内存中 连接关闭。但是,扩展不会自动进行 注册到后续数据库连接。这使它成为可能 加载实现新 VFS 的扩展。 持久加载和注册实现新 SQL 的扩展 函数、整理序列和/或虚拟表,使得那些 添加的功能可用于所有后续数据库连接, 然后,初始化例程还应该在将注册这些服务的子函数上调用 sqlite3_auto_extension()。

vfsstat.c 扩展 显示一个可加载扩展的示例,该扩展永久注册两者 新的 VFS 和新的虚拟表。该扩展中的 sqlite3_vfsstat_init() 初始化例程仅调用一次,当 首先加载扩展。它注册了新的“vfslog”VFS 一次,它返回SQLITE_OK_LOAD_PERMANENTLY,以便使用的代码 要实现“vfslog”,VFS 将保留在内存中。初始化例程 还在指向“vstatRegister()”的指针上调用 sqlite3_auto_extension(函数,以便所有后续数据库连接都将调用 “vstatRegister()”函数,因此注册 “vfsstat”虚拟表。

6. 静态链接运行时可加载扩展

完全相同的源代码可用于运行时可加载 共享库或 DLL,并作为与 应用。这提供了灵活性,并允许你重复使用相同的内容 以不同的方式编写代码。

要静态链接扩展,只需添加 -DSQLITE_CORE 编译时选项。SQLITE_CORE宏会导致SQLITE_EXTENSION_INIT1 并将宏SQLITE_EXTENSION_INIT2为无操作。然后修改你的 应用程序直接调用入口点,传入 NULL 指针 作为第三个“pApi”参数。

使用入口点名称尤为重要 基于扩展名文件名,而不是通用 “sqlite3_extension_init”入口点名称,如果将静态 链接两个或多个扩展。如果使用通用名称,则有 将是同一符号的多个定义,并且链接将失败。

如果要在应用程序中打开多个数据库连接, 而不是调用每个数据库的扩展入口点 连接 另外,您可能需要考虑使用 sqlite3_auto_extension() 接口来注册您的扩展和 使它们在每个数据库连接时自动启动 已打开。您只需注册每个扩展一次,就可以 在 main() 例程的开头附近执行此操作。使用 sqlite3_auto_extension() 接口注册扩展使 您的扩展就像它们内置在核心 SQLite 中一样 - 它们 每当打开新的数据库连接时,自动存在 无需初始化。只要确保完成任何 您需要先使用 sqlite3_config() 完成的配置 注册扩展,因为 sqlite3_auto_extension() 接口隐式调用 sqlite3_initialize()。

7. 实施细节

SQLite 使用 sqlite3_vfs 对象的 xDlOpen()、xDlError()、xDlSym()和 xDlClose()方法。这些方法是使用 unix 上的 dlopen()库(这解释了为什么 SQLite 通常 需要链接到 Unix 系统上的“-ldl”库) 并在 Windows 上使用 LoadLibrary()API。在自定义 VFS 中 不寻常的系统,这些方法都可以省略,在这种情况下 运行时扩展加载机制将不起作用(尽管 您仍然可以静态链接扩展代码,假设 入口指针是唯一命名的)。 SQLite可以用SQLITE_OMIT_LOAD_EXTENSION进行编译,以省略扩展加载代码 从构建。

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

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

相关文章

Mysql-主从复制理解

环境&#xff1a;mysql&#xff0c;主从复制&#xff0c;必须有2个mysql实例&#xff0c;也就是说可以在一台电脑上安装2个msyql&#xff0c;或者2台服务器&#xff0c;一个主服务器&#xff0c;一个从服务器 在实际的生产中&#xff0c;为了解决Mysql的单点故障已经提高MySQL的…

Tomcat安装和配置以及多实例部署(附脚本)

TOMCAT详细部署 Tomcat服务器简介核心组件Tomcat 各组件及关系工作流程 Tomcat server.xml 配置详解serverserviceConnectorEngineHostContextValve 阀门 Tomcat部署与安装部署脚本主要目录说明 Tomcat多实例部署扩展和优化 Tomcat 的 catalina.sh 文件以调整 JVM 参数 Tomcat服…

前端工程化Vue使用Node.js设置国内高速npm镜像源(踩坑记录版)

前端工程化Vue使用Node.js设置国内高速npm镜像源&#xff08;踩坑记录版&#xff09; 此篇仅为踩坑记录&#xff0c;并未成功更换高速镜像源&#xff0c;实际解决方法见文末跳转链接。 1.自身源镜像 自身镜像源创建Vue项目下载速度感人 2.更改镜像源 2.1 通过命令行配置 前提…

K8s容器部署maven项目

最近在整一整套devops自动化持续集成的东西&#xff0c;一开始就做好了踩坑的准备。 failed to verify certificate: x509: certificate signed by unknown authority 今天在执行kubectl get nodes的时候报的证书验证问题&#xff0c;看了一圈首次搭建k8s的都是高频出现的问题…

泰坦尼克号乘客生存情况预测分析2

泰坦尼克号乘客生存情况预测分析1 泰坦尼克号乘客生存情况预测分析2 泰坦尼克号乘客生存情况预测分析3 泰坦尼克号乘客生存情况预测分析总 背景描述 Titanic数据集在数据分析领域是十分经典的数据集&#xff0c;非常适合刚入门的小伙伴进行学习&#xff01; 泰坦尼克号轮船的…

基于LM Studio + LLaMA3 建立本地化的ChatGPT

4月19日&#xff0c;Facebook母公司Meta重磅推出了Llama3。即便大家现在对于大厂和巨头频繁迭代AI模型的行为已经见怪不怪&#xff0c;Meta的Llama3仍旧显得与众不同&#xff0c;因为这是迄今最强大的开源AI模型。LLaMA模型通常采用了类似于GPT&#xff08;由OpenAI开发&#x…

【Qt】error LNK2001: 无法解析的外部符号

参考&#xff1a;Qt/VS LNK2019/LNK2001&#xff1a;无法解析的外部符号_qt lnk2001无法解析的外部符号-CSDN博客 微软官方报错文档-链接器工具错误 LNK2019 __declspec error LNK2001: 无法解析的外部符号 "__declspec(dllimport) 原因 以这种为前缀的基本上跟库相关…

pnpm install报错 Value of “this“ must be of type URLSearchParams

执行pnpm install的时候就报错Value of “this” must be of type URLSearchParams 由于之前执行没有出现过这个问题&#xff0c;最近在使用vue3所以使用了高版本的node&#xff0c;怀疑是node版本的问题。 解决&#xff1a; 检查node版本 node -v当前使用的是20.11.0的 修改…

《ESP8266通信指南》7-Arduino 开发8266的环境配置与示例代码烧录

往期 《ESP8266通信指南》6-创建TCP服务器&#xff08;AT指令&#xff09;-CSDN博客 《ESP8266通信指南》5-TCP通信透传模式(AT指令)-CSDN博客 《ESP8266通信指南》4-以Client进行TCP通信&#xff08;AT指令&#xff09;-CSDN博客 《ESP8266通信指南》3-常用AT指令详解-826…

elasticsearch 常用语法汇总

文章目录 前言elasticsearch 常用语法汇总1. 创建索引2. 检索索引信息3. 删除索引4. 文档操作4.1. 对blog_new索引指定文档ID新增4.2. 对blog_new索引不指定文档ID新增&#xff0c;随机文档ID:4.3. 获取文档4.4. 更新文档4.5. 删除文档 5. 查询5.1. 匹配查询5.2. 范围查询5.3. …

HackMyVM-Vulny

目录 信息收集 arp nmap nikto WEB信息收集 主页信息收集 gobuster RCE漏洞 反弹shell 提权 系统信息收集 横向渗透 flock提权 信息收集 arp ┌──(root㉿0x00)-[~/HackMyVM] └─# arp-scan -l Interface: eth0, type: EN10MB, MAC…

从NuGet获取OpenTK

OpenTK是一个开源、跨平台的游戏开发库&#xff0c;由MonoGame团队创建。它为C#开发者提供了一个简单易用的接口&#xff0c;以便使用OpenGL、OpenAL和OpenCL进行3D渲染、音频处理和并行计算。OpenTK的目标是提供一个一致且高效的框架&#xff0c;让开发者能够专注于构建他们的…

鸿蒙(HarmonyOS)性能优化实战-Trace使用教程

概述 OpenHarmony的DFX子系统提供了为应用框架以及系统底座核心模块的性能打点能力&#xff0c;每一处打点即是一个Trace&#xff0c;其上附带了记录执行时间、运行时格式化数据、进程或线程信息等。开发者可以使用SmartPerf-Host调试工具对Trace进行解析&#xff0c;在其绘制…

arcgis js 4.x加载SceneLayer并实现基于属性查询定位及高亮

一、代码 <!DOCTYPE html> <html> <head><meta charset"utf-8" /><meta name"viewport" content"widthdevice-width, initial-scale1,maximum-scale1,user-scalableno"><title></title><link rel…

python批量删除文件

python批量删除文件 1、查询与删除2、添加模块到地址中3、批量删除多个路径中不需要导出的文件 1、查询与删除 mport osdef get_files_in_folder(folder_path):files []for file in os.listdir(folder_path):if os.path.isfile(os.path.join(folder_path, file)):files.appen…

微信小程序:5.数据绑定

在Data中定义数据早wxml中进行数据使用 在data中定义数据 在页面对应的js对象中找到data&#xff0c;然后把数据进行定义即可 Page({data: {motto: Hello World,userInfo: {avatarUrl: defaultAvatarUrl,nickName: ,},hasUserInfo: false,canIUseGetUserProfile: wx.canIUse…

关于OSPF报文学习

目录 一.OSPF学习补充 &#xff08;1&#xff09;OSPF报文头部 &#xff08;2&#xff09;ospf建立邻居关系 1.Hello报文——建立邻居关系 2.hello报文头部 &#xff08;3&#xff09;OSPF建立邻接关系 1.发送DD报文 2.DD报文头部 &#xff08;4&#xff09;关于DR,BD…

pyqt QSplitter控件

pyqt QSplitter控件 QSplitter控件效果代码 QSplitter控件 PyQt中的QSplitter控件是一个强大的布局管理器&#xff0c;它允许用户通过拖动边界来动态调整子控件的大小。这个控件对于创建灵活的、用户可定制的用户界面非常有用。 QSplitter控件可以水平或垂直地分割其包含的子…

Bytebase 2.16.0 - 支持 Oracle 和 SQL Server DML 变更的事前备份

&#x1f680; 新功能 支持 Oracle 和 SQL Server DML 变更的事前备份。 支持在 SQL 编辑器中显示存储过程和函数。 支持兼容 TDSQL 的 MySQL 和 PostgreSQL 版本。 支持把数据库密码存储在 AWS Secrets Manager 和 GCP Secret Manager。 支持通过 IAM 连接到 Google Clou…