[pgrx开发postgresql数据库扩展]3.hello world全流程解析

news2024/11/15 21:31:40

数据库的扩展开发框架

一般来说,数据库的扩展开发主要有的目的就是扩展数据库引擎的能力(不管是用pgrx还是其他的框架都一样):

例如PostgreSQL上最著名的扩展PostGIS,就是扩展了PG数据库的空间数据支持能力,目前PostGIS已经成了使用最广泛的开源空间数据库扩展。

Esri从10.7版本开始,逐步支持PostGIS,而到10.8之后,所有产品线已经默认全部支持PostGIS,所以Esri的ArcGIS产品线,系统默认支持SDE/PostGIS双线空间数据库引擎)。

如果要扩展数据库的能力,那么一般来说需要以下两种能力:

  1. 对于数据库引擎自身的全面操作能力,例如从最基础的SQL的能力,到函数定义、触发性、存储过程等;又例如更深度一些的数据库配置的控制能力,甚至与数据库的内核控制能力。只有达到这种能力,才能被称之为一个合格的数据库扩展开发框架。
    例如我需要让数据库直接支持我们特别定义的一种文件格式,在数据库层面做到能够导入导出,就必须要进行扩展开发了。
  2. 就是让数据库系统能够跳出数据库引擎自身的局限,去操作和执行一些更强的能力。例如对于关键数据项进行触发性的监控,一旦特定条件被触发,则调用扩展语言能力,取发送警报信息,设置锁死数据库这种高级能力。
    本例中的安全监控能力,通常的实现是依赖与数据库管理系统来做的,也就是第三方应用,对数据库进行监控,这样无论是性能、效率、稳定性还是安全性,都远远不如把这种能力放到数据库引擎上来做。

——题外话:有同学看到这里,可能会说:数据库本来就是一个系统里面压力最大的部分,在架构设计的时候都巴不得把所有的功能都从数据库上挪走,以减轻数据库的压力,你这样做,不是反其道而行之么?

常见高并发系统里面,数据库确实是最容易被攻破的环节,是因为相对于微服务架构下,天生就具备了容易横向扩展和负载均衡的应用系统而言,数据库的横向扩展的难度和成本都是指数级的,所以大部分高并发架构设计中,都使用了各种手段来保护数据库,例如Redis缓存、队列、读写分离等,希望把数据库的压力都分配出去。

而我们这里采用数据库扩展开发,让一部分功能直接在数据库引擎上执行,则有三个方面的考量:

  1. 对于一些并发量不大,但是对于计算效率要求比较高的系统,数据库压力并不是瓶颈,反而对于CPU密集型运算来说,跑在数据库引擎上这种在“最贴近数据的地方做运算”的优势更大。
  2. 一些功能,通常是利用第三方应用来监控数据库(例如安全监控,或者信息更新同步),会造成复杂的交互、以及更长的逻辑链,也增大了系统风险的概率。反而把这些功能放到数据库系统上,能够有效的减少系统的复杂性。
  3. 从IO而言,写在数据库扩展函数里面的功能,在数据库引擎上做计算,能够最大限度的减少数据库与应用系统之间的数据IO。

那么从今天开始,我们就进入pgrx的开发环节,我们来看看如何开发一个数据库扩展功能。

注意!!写在pgrx之前的话:

并不是所有场景都需要(或者适合)用rust来写的,绝大部分操作数据库的功能和计算,用SQL就已经足够了!
本系列中,所有的案例,仅用于说明pgrx的能力,而并非是说这样做比用SQL更合适。反之:对于操作数据库本身的部分,大部分能用SQL来实现的东西,都比做一个扩展开发要更加合适。

pgrx基础功能函数的开发

前言说明:

本系列开发,采用vscode远程连接windows 10 wsl2的ubuntu 的模式,具体安装方式,请自行查阅相关文档,基础环境如下:

系统环境:

  • 操作系统版本 : Ubuntu 20.04.5 LTS
  • gcc 版本: 9.4.0
  • Clang版本:10.0.0
  • rust/cargo版本:1.68.0
  • pgrx版本:0.7.4
  • postgresql版本:11- 15
    • 默认在postgresql 13下进行测试。

以上内容安装请看上一篇文章

开发环境:

  • vscode 版本: 1.77.3
  • 插件:
    • rust-analyzer v0.3.1481 (rust插件)
    • Rust Syntax v0.6.1 (rust语法提示)
    • WSL v0.77.0 (vscode 连接wsl插件)
    • CodeLLDB v1.9.0 (C/C++运行即调试插件)

以上版本号截止到2023年4月,之后的话大家用更新的版本,也是可以的。

pgrx的hello world

我们可以从pgrx框架自动生成的脚手架来看看一个hello world程序的结构:

建立的是一个标准的rust cargo模式的工程,一般来说,要关注就这两个文件,lib.rs是rust功能模块主代码,一个rust工程一般只有一个lib文件,而Cargo.toml则是工程的配置文件,二者的具体的功能和作用,大家而已参考Rust相关基础教程。

pgrx的Cargo.toml内容如下:

重点关注几个设置就行:

  1. features中的default设置,pgrx脚手架给出的默认是pg13的版本,同时告诉你可以在11到15之间进行选择(如果你的开发环境和我一样,把这些都安装了的话)。
  2. dependencies中设置的pgrx版本,一般默认都会给你最新版本,没啥说的,不过这个设置是cargo最中主要的设置,以后我们要引入其他的包,也都要写在这个地方。

里面的这些内容,你不用pgrx来生成,也是可以的,自己手写一样能够有效果,同样的,你如果你不安装pgrx扩展,全部手写也可以做到,只是没有这些脚手架,各种编译的命令参数和环境设置,会让写到怀疑人生……

之后我们来看看lib.rs中的内容:

我们分成三部分来讲解:

第一部分:逻辑功能块:

use pgrx::prelude::*;

这句代码表示需要引用pgrx包里面的prelude模块,这个模块定义和声明了pgrx里面的各种通用函数、设置和宏,一般来说,有这句代码,pgrx里面常用的功能就到齐了。

pgrx::pg_module_magic!();

这句代码是调用pgrx定义的模块宏,如果不懂什么叫做宏,你就可以理解为,只要有这句话,整个lib的工程,就会被自动识别为postgresql的一个扩展模块,可以在postgresql被自动识别和加载就可以了。

#[pg_extern] fn hello_pgrxdemo() -> &'static str { "Hello, pgrxdemo" }

这个方法就是pgrx的hello world方法,可以看见代码量非常的简洁。

我们逐行进行解读

首先第一句

#[pg_extern]

#[]是一个是Rust中的注解属性,用于编译环境的注解,类似于Python里面的装饰器和Java里面annotation,

而pg_extern表示要用pg_extern这个扩展注释来封装下面Rust函数,使其接口符合 postgres extension 的 C ABI,以及处理 Rust 数据结构和 postgres 内部数据结构的转换。

可以如果你对这些概念都不熟悉的话,仅需要记住在Rust的函数上面,加载了这个注解属性,这个方法就可以被编译成PG兼容的函数了就行。

下面就是我们要写的函数了,这是一个标准的rust函数,结构如下:

fn 函数名(可选参数1: 参数类型1,……) ->返回值类型{ 函数体 }

其中,fn是函数定义的关键字,-> 表示本函数有返回值,这里要注意的是'static str这返回值的写法,单引号是rust里面生命周期声明方法,'static表示声明这个函数的返回值是一个全局(生命周期)静态的字符串。

有关生命周期的问题,请打架查阅Rust相关教程和材料。

题外话,rust语言别认为学习曲线最陡峭的语言之一,一般来说,要学会Rust会要过三大天坑:

一号天坑就是所有权与生命周期问题,这个坑起码能埋掉80%以上的初学者。

二号天坑就是特性(trait)与泛型编程,这个坑能把通过了一号天坑的人里面,再埋掉50%以上。

三号天坑就是异步编程,这个也被认为是rust里面的精华,但是也是最难通过一个坑,这个坑能把通过了前面两关的同学,最后再坑进去50%。

所以,100个进入Rust的初学者,能够通过这三大天坑的,就不到5个人了……

题外话到到此为止,不过大家要想好好学习一下Rust的话, 切记趟这三大天坑的时候要注意。

函数体里面就是一句问好:"hello pgrxdemo",看到这里又有同学问,我们返回的字符串,为什么没有用关键字return呢?

这也是Rust的一个特性,我们函数体里面那个hello pgrxdemo,不但没有return,而且没有;号结尾,这种没有分号的语句,在rust叫做表达式,rust任何表达式都表示(应该)有返回值,如果函数的最后一句是一个表达式的话,则这个表达式的返回值就是这个函数的返回值了。

这个函数可以直接返回一个静态字符串(把静态生命周期去掉也可以,静态字符串对系统性能更友好而已)。

然后在看看lib.rs的第而部分:

这里是pgrx给我们预先生成的一个用于测试的mod,并且给了两个注解属性:

  1. #[cfg(any(test, feature = "pg_test"))] cfg表示使用属性来进行条件编译,这里的条件本mod下面的所有方法,都用pg_test条件进行测试。
  2. #[pg_schema]属性表示测试方法会运行在一个postgresql的schema中,如果指定了自己的schema,则运行在自己制定的,如果没有指定,则运行在默认的schema中。
在rust代码里面,注释为test的mod,可以独立运行测试,但是不会在release中进行发布。

最后看看第三部分:

这部分也是pgrx自动生成的,用于初始化测试过程和安装打包,如果你有自定义的postgresql配置,也可以写在这里面,一般情况下,我们不去修改这一部分。

接下去,我们看看在运行的过程中,会发生什么事情?

首先输入debug运行模式的命令:

cargo pgrx run

编译器进行debug模式编译,然后自动启动postgresql的命令模式,主要干了以下几件事情:

  1. 首先会把工程里面的pgrxdemo.control这个文件拷贝到设置的pg环境下面的extension目录下面,这个文件主要的内容是进行一些常规声明如下:

comment = 'pgrxdemo: Created by pgrx' default_version = '@CARGO_VERSION@' module_pathname = '$libdir/pgrxdemo' relocatable = false superuser = true

一般我们不用去改他(除非你有一些特殊的环境设置)

  1. 会把你的工程编译好的so库文件,写到你的pg环境下面的lib文件下,文件名通常是你工程的名称,我这里是:
    /usr/lib/postgresql/13/lib/pgrxdemo.so
  2. 会在pgrxdemo.control这个文件相同的位置,生成一个sql文件,这个文件主要定以的就是在sql中调用你的扩展函数的声明了,如下所示:

我们去文件系统下面看看:

so文件:

control和sql文件:

注意,只要control和sql文件存在于extension文件里面,如果格式内容正确,postgresql的扩展就能够自动找到并且加载为pg的可用扩展,如下所示:

这里面的版本和说明信息,都是control文件中的内容。

而installed_version(目前已安装版本)为Null,说明系统中可用,但是还没有安装,接下去,我们只需要在数据库里面创建一下扩展,就可以用了。

创建扩展以及执行语句,如下:

至此,一个pgrx扩展的hello world,就完整写完了,里面每个步骤的代码和意义,也做了一个简单的解释。

比较简单……我觉得……是吧……

待续未完。

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

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

相关文章

Linearx配置环境

代码地址 gitssh.dev.azure.com:v3/linearx/PowerDDS/PowerDDS LinearX-5G Wifi pwd: 50186058 Windows报错可以搜索错误代码找官方给出的解决方案 最新版本cmake:ubuntu 20.04安装(升级)cmake - 知乎 (zhihu.com) gtest:gtest的安装_liuzubing的博客…

图论 Kruskal 最小生成树算法

前置知识 关于最小生成树 先说「树」和「图」的根本区别:树不会包含环,图可以包含环 树就是「无环连通图」 生成树是含有图中所有顶点的「无环连通子图」 你要保证这些边: 1、包含图中的所有节点。 2、形成的结构是树结构(即不…

NFS共享存储服务

目录 一、NFS简介二. NFS工作原理实验:准备一台服务器,一台客户端。实现共享目录服务器上发布共享目录配置操作客户端配置操作 总结 一、NFS简介 NFS(Network File System 网络文件服务) NFS 是一种基于 TCP/IP 传输的网络文件系…

五一国际劳动节知多少!祝五一劳动节快乐! Happy International Workers‘Day!

五一国际劳动节简称五一节,在每年的5月1日,它是全世界劳动人民的共同节日。5.1 International labor Days call 5.1 sections, May 1 in every year. It is the whole world labor common festival of the people. 劳动是人类的幸福之源。 Work is the t…

JQuery-原理示意图-- 选择器-- 选择器综合代码--jQuery 的 DOM 操作--增删改查节点--常用遍历节点方法--多选框应用--全部综合代码

目录 JQuery 基本介绍 jQuery 的原理示意图 JQuery 基本开发步骤 说明: jQuery简单示例 jQuery 对象和 DOM 对象 什么是 jQuery 对象 DOM 对象转成 jQuery 对象 应用实例 jQuery 对象转成 DOM 对象 代码演示 jQuery 选择器 jQuery 选择器介绍 jQuery 选择器的优…

Adaptive AUTOSAR 文档官方如何阅读

目前很多关于 Adaptive AUTOSAR 的文章都是官方文档的简化翻译,不如直接看官方文档更全面深入。 Adaptive AUTOSAR 文档官方下载地址 Adaptive Platform AUTOSARhttps://www.autosar.org/standards/adaptive-platform About The AUTOSAR Adaptive Platform impl…

JavaScript 教程---菜鸟教程

文章目录 JavaScript 教程JavaScript 输出JavaScript 对象JavaScript 函数JavaScript 事件 JS 函数JS 类JS HTML DOMJS 高级教程JS 浏览器 BOMJS 库 JavaScript 教程 JavaScript 输出 JavaScript 可以通过不同的方式来输出数据 使用window.alert()弹出警告框。 <script&…

物联网产品的开发的难点,致命点是什么?

物联网产品的开发的难点&#xff0c;致命点是什么&#xff1f; 当下是万物互联的时代&#xff0c; 物联网产品本身的难度因行业而异。但是物联网设备上云通信交互就成了各个行业需要首先解决的问题。 物联网通信问题从产品设计一开始&#xff0c;如果不能很好的解决&#xff0c…

C++引用详解

1.引用概念 引用不是新定义一个变量&#xff0c;而是给已存在变量取了一个别名&#xff0c;编译器不会为引用变量开辟内存空间&#xff0c;它和它引用的变量共用同一块内存空间。 比如&#xff1a; 这是简单的引用 注意&#xff1a;引用类型必须和引用实体是同一种类型。 2.…

数据仓库技术与Hive入门

文章目录 数据仓库基本概念场景案例主要特征主流开发语言-SQL数仓开发语言概述SQL语言介绍结构化数据SQL语法分类 Apache Hive入门Apache Hive 安装部署元数据 Hive SQL语言 数据仓库 基本概念 数据仓库(Data Warehouse,简称数仓、DW)&#xff0c;是一个用于存储&#xff0c;分…

FMC128:具有出色的同步性能-8通道同步采集

板卡概述 FMC128 是一款 8 通道 250MHz 采样率 16 位 AD 采集 FMC子卡&#xff0c;符合 VITA57 规范&#xff0c;可以作为一个理想的 IO 模块耦合至 FPGA 前端&#xff0c;8 通道 AD 通过高带宽的 FMC 连接器&#xff08;HPC&#xff09;连接至 FPGA 从 而大大降低了系统信号…

八、vue_options之computed、watch属性选项

一、computed计算属性使用 &#xff08;1&#xff09;复杂data的处理方式 &#xff08;2&#xff09;computed 计算属性 computed计算属性初体验&#xff1a; 在我们通过Vue调用createApp方法传入一个对象的时候&#xff0c;我们之前写了data属性、methods属性&#xff0c;这…

关于一个C++项目的总结与反思:bosot搜索引擎

文章目录 写在前面关于这个项目的收获简单的项目介绍整体逻辑与第三方库每一步的具体细节util.hppparser.ccindex.hppsearcher.hpphttp_server.hpp其他模块 项目地址&#xff1a;boost_searcher: 项目&#xff1a;boost站内搜索 (gitee.com) 写在前面 这个项目是用C写的&…

聚焦能源 | 赛宁网安亮相2023年中国能源网络安全大会

​​4月21日&#xff0c;2023年中国能源网络安全大会&#xff08;以下简称“大会”&#xff09;在江苏南京成功落幕&#xff01;为贯彻国家网络强国战略&#xff0c;加强能源网络安全技术创新、成果应用、人才培养与技术交流&#xff0c;大会推出主旨论坛、案例交流、展览展示等…

python:根据灰度值检查成像是否存在黑图情况

一、需求描述 1、摄像机在拍照的时候&#xff0c;会打开闪光灯进行拍照&#xff0c;假如闪光灯在拍照之后打开&#xff0c;就会产生黑图 2、因此&#xff0c;我们需要摄像机采集很多图片&#xff0c;检查是否每次拍照都是正常的 3、我们可以通过人眼进行查看&#xff0c;但是…

SpringCloud入门实战(七)-Hystrix服务熔断入门案例

&#x1f4dd; 学技术、更要掌握学习的方法&#xff0c;一起学习&#xff0c;让进步发生 &#x1f469;&#x1f3fb; 作者&#xff1a;一只IT攻城狮 。 &#x1f490;学习建议&#xff1a;1、养成习惯&#xff0c;学习java的任何一个技术&#xff0c;都可以先去官网先看看&…

Mysql 学习(七)独立表结构存储 一

独立表空间结构 InnoDB有很多类型表空间&#xff0c;这边主要是介绍独立表空间结构&#xff0c;因为这种会用的比较多讲之前我们先思考一个问题&#xff0c;如果我们以页为单位来分配存储空间的话&#xff0c;那两个页之间的物理距离可能很远&#xff0c;因为这是随机的&#…

2023有哪些适合学生用蓝牙耳机?300左右最好的蓝牙耳机推荐

2023年了&#xff0c;蓝牙耳机常常伴随手机出现在人们的日常生活当中&#xff0c;不管是听歌、运动、甚至玩游戏&#xff0c;大多数人都会选择戴蓝牙耳机。那么&#xff0c;有哪些适合学生用的蓝牙耳机&#xff1f;针对这个问题&#xff0c;我来给大家推荐几款300左右最好的蓝牙…

故障分析 | 从 Insert 并发死锁分析 Insert 加锁源码逻辑

作者&#xff1a;李锡超 一个爱笑的江苏苏宁银行 数据库工程师&#xff0c;主要负责数据库日常运维、自动化建设、DMP平台运维。擅长MySQL、Python、Oracle&#xff0c;爱好骑行、研究技术。 本文来源&#xff1a;原创投稿 *爱可生开源社区出品&#xff0c;原创内容未经授权不得…

Python初学小知识(十四):数据分析处理库Pandas

Python初学小知识&#xff08;十四&#xff09;&#xff1a;数据分析处理库Pandas 十八 Pandas1 文件读取1.1 读取csv1.2 读取txt1.3 读取excel&#xff08;xlsx&#xff09; 2 内容读取2.1 读取行2.2 读取列 3 数据处理3.1 加减乘除3.1.1 列 与 元素3.1.2 列 与 列 3.2 最值、…