PostgreSQL-UDF用户自定义函数-扩展插件

PostgreSQL-UDF用户自定义函数-扩展插件

零、前置条件

  1. ggc
  2. postgresql

一、创建 .c 和 .sql 文件

创建.c文件

  • 进入PG源码的contib/目录下面,这个目录下面都是用于PG进行功能扩展的插件。
  • 创建我们的插件(UDF同义词:插件;扩展;用户自定义函数)目录demo/
  • 在我们的插件目录下创建.c.sql文件,后续第二步中还会创建用于编译和链接的Makefile文件和.control文件。
[root@localhost ~]# cd /root/pgsoft/postgresql-15.3/contrib/
[root@localhost contrib]# mkdir demo
[root@localhost contrib]# cd demo
# 创建.c文件
[root@localhost demo]# vim demo.c
  • UDF函数的.c文件写法见该链接第二步。
  • .c文件内容如下:
#include "postgres.h"
#include "fmgr.h"

#ifdef PG_MODULE_MAGIC
PG_MODULE_MAGIC;
#endif

PG_FUNCTION_INFO_V1(my_sum); //PG中需要使用PG_FUNCTION_INFO_V1()来声明函数名

Datum my_sum(PG_FUNCTION_ARGS); 

Datum my_sum(PG_FUNCTION_ARGS){ //定义函数体,这里定义的函数体功能是返回传参的两整型数相加的结果
        

        int32 a = PG_GETARG_INT32(0);
        int32 b = PG_GETARG_INT32(1);

        int32 sum = a + b;
        PG_RETURN_INT32(sum);

}

创建.sql文件

  • .sql文件中主要是写入创建FUNCTIONTYPE的SQL语句。
  • vim新建一个以插件名+插件版本号命名的.sql文件(这里demo是插件名,--1.0是版本号)。
[root@localhost demo]# vim demo--1.0.sql
  • .sql具体内容如下:
CREATE FUNCTION my_sum(INTEGER,INTEGER) 
RETURNS INTEGER 
AS '$libdir/demo' 
LANGUAGE C STRICT;
  • 注意:SQL语句中的函数名要和上面.c中定义的函数保持一致。
  • 其中$libdir这个变量是PG安装位置下的静态库文件的默认存储路径,可以用[root@localhost ~]# pg_config --pkglibdir这一命令查看具体的路径,可以不用管,后面直接接与插件名一致的目录即可,这里接的是demo
  • 如果.c文件中定义了多个函数,.sql文件中的AS后面需要指明是demo.c中的哪一个函数,即:
CREATE FUNCTION …
… …
AS '$libdir/demo', 'my_sum'
… …

二、创建 .control 和 Makefile 文件

创建 .control 文件

  • 在PostgreSQL中,后缀为.control的文件是一个扩展的控制文件。它用于管理和描述特定扩展的元数据和配置信息。
  • 控制文件通常与扩展相关联,并存储了有关扩展的重要信息,例如扩展的名称、版本、所需依赖项等。这些文件还可以包含其他配置选项,以更好地定义和管理扩展的行为。
  • 通过使用.control文件,PostgreSQL能够根据需要加载和卸载扩展,并确保正确配置和使用扩展。这些文件对于扩展的安装、更新和卸载过程都起着重要作用。
  • 总结:.control文件是PostgreSQL中扩展的元数据文件,用于管理和配置扩展的属性和行为。
[root@localhost demo]# vim demo.control
  • .control文件基本内容如下:
comment = 'test demo'
default_version = '1.0'
module_pathname = '$libdir/demo'
relocatable = true
  • comment配置项:用于提供关于扩展的注释或描述性文本。它允许开发人员向用户提供有关扩展功能、用途或其他相关信息的说明。这些注释可以帮助用户更好地理解和使用扩展.
  • relocatable配置项:用于指定扩展是否可重定位。如果设置为true,则表示扩展可以在不重新编译数据库的情况下移动到不同的安装位置。这对于在多个数据库实例之间共享和部署扩展非常有用。默认情况下,该配置项的值是false
  • 注意:default_version要与最新版本的.sql文件名中的版本号保持一致。

创建 Makefile 文件

  • Makefile文件本质上是shell命令的集合,用于一系列源代码文件的自动化编译,用make指令执行一个Makefile文件,可以根据文件中的编译规则对一系列源代码文件进行不同的编译。
  • 这里贴一个Linux下编译链接相关文件的流程说明(根据自己的理解总结的图,有错误敬请指出):
    在这里插入图片描述
  • 回到正题,Makefile文件由变量们和编译规则构成:
    • 定义变量的基本格式是变量名 = 变量值,使用变量的基本格式和shell一致$(变量名)
    • 对某个源码文件的编译规则编写的语法基本格式如下:
目标文件1:依赖文件1

(Tab键)规则1(依赖文件1怎么生成目标文件1的,也就是用依赖文件生成目标文件的方法)

目标文件2:依赖文件2

(Tab键)规则2(依赖文件2怎么生成目标文件2的)
  • 依赖文件对应上图.c.cpp等源码文件,目标文件对应上图中.o文件。
  • 规则对应编译命令gcc [编译选项] (编译对象)
  • 实例:
demo.o:demo.c
	gcc -c demo.c
  • 更多Makefile格式相关的内容见 Makefile-详细说明 和 手把手教你写一个 Makefile 文件。
  • Makefile基本内容如下:
MODULES = demo

EXTENSION = demo
DATA = demo--1.0.sql 
PGFILEDESC = "demo - various functions that return tables" # 描述
OBJS = demo.o # 待生成的目标文件的名字,可以有多个,用空格分开
CC = gcc # 编译器的名称

REGRESS = tablefunc

LDFLAGES_SL += $(filter -lm, $(LIBS)) # 这一句的作用是如果有多个源码文件编译生成的.o目标文件,把这些.o文件打包成一个静态库文件,什么是打包?为什么要打包?什么是链接?解释均见上图

# 下面这一段中主要是一个条件分支语句,分别是用PGXS和不用PGXS进行扩展编译的情况。
# 变量PGXS:如果您正在考虑contribute PostgreSQL扩展模块,那么为它们建立一个可移植的构建系统可能相当困难。
# 因此,PostgreSQL安装为扩展提供了一个称为PGXS的构建基础设施,从而可以简单地针对已经安装的服务器来构建简单的扩展模块。
# PGXS主要用于包含C代码的扩展,尽管它也可以用于纯SQL扩展。
# 请注意,PGXS并不是一个通用的构建系统框架,可以用来构建任何与PostgreSQL接口的软件;它简单地自动化了简单服务器扩展模块的通用构建规则。对于更复杂的包,您可能需要编写自己的构建系统。

# 以上是对PGXS的解释,总结来说就是更方便用户自己进行扩展编译的一个模块
# ifdef NO_PGXS,如果不用PGXS进行编译,需要利用Makefile.global文件中指定的pg_config中includefir和libdir指明lib库和include库的位置,如下图
# 走上面这个条件分支编译时有可能会出现缺少一些依赖文件的情况,需要在源码中找到文件复制到demo/目录下来
# else,就是用PGXS编译的情况(可以选择编译时加参数 USE_PGXS=1) ,此时 Makefile 会通过 abase 自带命令 pg_config 来查找 lib 库和 include 库的位置,而命令 pg_config 已默认加载在数据库 owner 的 PATH 环境变量中,可直接使用。

# 总之下面这一段可以直接照搬,不用修改

# USE_PGXS = 1,如果加了这一句,进入else的条件分支
ifdef NO_PGXS
subdir = contrib/extensions
top_builddir = ../..
include $(top_builddir)/src/Makefile.global
include $(top_srcdir)/contrib/contrib-global.mk
else # = ifdef USE_PGXS
PG_CONFIG = pg_config
PGXS := $(shell $(PG_CONFIG) --pgxs)
include $(PGXS)
endif

  • PG源码地址/src/Makefile.global文件截图如下:
    在这里插入图片描述

三、编译 & 链接

  • 在demo目录下执行makemake install
[root@localhost demo]# make
gcc -std=gnu99 -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Werror=vla -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -g -O0 -fPIC -I. -I./ -I/opt/pgsql-15.3/include/server -I/opt/pgsql-15.3/include/internal  -D_GNU_SOURCE   -c -o demo.o demo.c -MMD -MP -MF .deps/demo.Po
gcc -std=gnu99 -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Werror=vla -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -g -O0 -fPIC demo.o -L/opt/pgsql-15.3/lib   -Wl,--as-needed -Wl,-rpath,'/opt/pgsql-15.3/lib',--enable-new-dtags  -shared -o demo.so

# 编译成功之后会出现 demo.o 和 demo.so 两个文件
[root@localhost demo]# ls
demo.c  demo.control  demo.o  demo.so  Makefile

[root@localhost demo]# make install
/usr/bin/mkdir -p '/opt/pgsql-15.3/share/extension'
/usr/bin/mkdir -p '/opt/pgsql-15.3/share/extension'
/usr/bin/mkdir -p '/opt/pgsql-15.3/lib'
/usr/bin/install -c -m 644 .//demo.control '/opt/pgsql-15.3/share/extension/'
/usr/bin/install -c -m 644 .//demo--1.0.sql  '/opt/pgsql-15.3/share/extension/'
/usr/bin/install -c -m 755  demo.so '/opt/pgsql-15.3/lib/'

# 扩展安装成功之后,PG安装目录下的./share/extensions/目录下会出现demo--1.0.sql文件和demo.control文件
[root@localhost demo]# ls /opt/pgsql-15.3/share/extension/
demo--1.0.sql     plpgsql.control             postgres_fdw.control
demo.control      postgres_fdw--1.0--1.1.sql
plpgsql--1.0.sql  postgres_fdw--1.0.sql

四、psql(或者其他PG backend)中创建扩展

posgres=# create extension demo;
CREATE EXTENSION
posgres=# 
posgres=# select my_sum(1,2);
 my_sum 
--------
      3
(1 row)

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

gitee(码云)如何生成并添加公钥,以及配置用户信息

一,简介 在使用Gitee的时候,公钥是必须的,无论是克隆还是上传。本文主要介绍如何本地生成和添加公钥到服务器,然后配置自己的用户信息,方便日后拉取与上传代码。 二,步骤介绍 2.1 本地生成公钥 打开git ba…

【SpringBoot】| 接口架构风格—RESTful

目录 一:接口架构风格—RESTful 1. 认识RESTful 2. RESTful 的注解 一:接口架构风格—RESTful 1. 认识RESTful (1)接口 ①接口: API(Application Programming Interface,应用程序接口&…

Django的简介安装与配置及两大设计模式

一.Djang的介绍 1.Django是什么 Django 是使用 Python 语言开发的一款免费而且开源的 Web 应用框架。 由于 Python 语言的跨平台性,所以 Django 同样支持 Windows、Linux 和 Mac 系统。 在 Python 语言炽手可热的当下,Django 也迅速的崛起,在…

文件的导入与导出

文章目录 一、需求二、分析1. Excel 表格数据导出2. Excel 表格数据导入一、需求 在我们日常开发中,会有文件的导入导出的需求,如何在 vue 项目中写导入导出功能呢 二、分析 以 Excel 表格数据导出为例 1. Excel 表格数据导出 调用接口将返回的数据进行 Blob 转换,附: 接…

【LangChain】P1 LangChain 应用程序的核心构建模块 LLMChain 以及其三大部分

LangChain 的核心构建模块 LLMChain LangChain 应用程序的核心构建模块语言模型 - LLMs提示模板 - Prompt templates输出解析器 - Output Parsers LLMChain 组合 LangChain 应用程序的核心构建模块 LangChain 应用程序的核心构建模块 LLMChain 由三部分组成: 语言…

前端原生写自定义旋转变换轮播图

html部分&#xff1a; <div class"banner_box"><div class"swiperWrapper" v-show"bannerList.length>0"><div class"swiper-item" :id"swiperSlide${index}" :class"{active:index0,next:index1,pr…

深度学习实战基础案例——卷积神经网络(CNN)基于SqueezeNet的眼疾识别|第1例

文章目录 前言一、数据准备1.1 数据集介绍1.2 数据集文件结构 二、项目实战2.1 数据标签划分2.2 数据预处理2.3 构建模型2.4 开始训练2.5 结果可视化 三、数据集个体预测 前言 SqueezeNet是一种轻量且高效的CNN模型&#xff0c;它参数比AlexNet少50倍&#xff0c;但模型性能&a…

Springboot写单元测试

导入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><exclusions><exclusion><groupId>org.junit.vintage</groupId><artifactId>junit-vintag…

Python学习笔记_基础篇(七)_常用模块

模块&#xff0c;用一砣代码实现了某个功能的代码集合。 类似于函数式编程和面向过程编程&#xff0c;函数式编程则完成一个功能&#xff0c;其他代码用来调用即可&#xff0c;提供了代码的重用性和代码间的耦合。而对于一个复杂的功能来&#xff0c;可能需要多个函数才能完成…

机器人CPP编程基础-03变量类型Variables Types

机器人CPP编程基础-02变量Variables 全文AI生成。 C #include<iostream>using namespace std;main() {int a10,b35; // 4 bytescout<<"Value of a : "<<a<<" Address of a : "<<&a <<endl;cout<<"Val…

详细记录Pycharm配置已安装好的Conda虚拟环境

当安装好conda环境之后&#xff0c;想要在Pycharm中使用&#xff0c;那么就要在Pycharm中导入&#xff0c;我这里使用的pycharm-professional-2023.2这个版本&#xff0c;下面是详细步骤&#xff1a; 1.打开File->Settings&#xff1a; 2.找到Project——>Python Inter…

网络层协议

网络层协议 IP协议基本概念协议头格式网段划分特殊的IP地址IP地址的数量限制私有IP地址和公网IP地址路由IP协议头格式后续 在复杂的网络环境中确定一个合适的路径 IP协议 承接上文&#xff0c;TCP协议并不会直接将数据传递给对方&#xff0c;而是交付给下一层协议&#xff0c;…

LeetCode Top100 Liked 题单(序号34~51)

​34. Find First and Last Position of Element in Sorted Array ​ 题意&#xff1a;找到非递减序列中目标的开头和结尾 我的思路 用二分法把每一个数字都找到&#xff0c;最后返回首尾两个数 代码 Runtime12 ms Beats 33.23% Memory14 MB Beats 5.16% class Solution {…

ssh远程连接服务器

一、远程连接服务器简介 二、连接加密技术简介 三、ssh服务配置 四、用户登录ssh服务 Enforcing会强制限制&#xff0c;如端口为22&#xff0c;可以访问&#xff0c;如果是2000端口&#xff0c;不能使用 Permissive是宽容的模式&#xff0c;不限制使用端口 Enforcing会重启失败…

Redis系列(一):深入了解Redis数据类型和底层数据结构

Redis有以下几种常用的数据类型&#xff1a; redis数据是如何组织的 为了实现从键到值的快速访问&#xff0c;Redis 使用了一个哈希表来保存所有键值对。 Redis全局哈希表&#xff08;Global Hash Table&#xff09;是指在Redis数据库内部用于存储所有键值对的主要数据结构。…

(三)行为模式:2、命令模式(Command Pattern)(C++示例)

目录 1、命令模式&#xff08;Command Pattern&#xff09;含义 2、命令模式的UML图学习 3、命令模式的应用场景 4、命令模式的优缺点 5、C实现命令模式的实例 1、命令模式&#xff08;Command Pattern&#xff09;含义 命令模式&#xff08;Command&#xff09;&#xff…

亚马逊、ebay、虾皮电商卖家如何做测评,提高店铺排名?

测评是什么呢&#xff1f; 不管是在亚马逊&#xff0c;速卖通&#xff0c;阿里国际&#xff0c;虾皮&#xff0c;Lazada&#xff0c;沃尔玛&#xff0c;美客多&#xff0c;ebay等跨境电商平台&#xff0c;测评都是成本最低且最有效的一种推广方式。 通俗来说&#xff0c;测评…

leetcode292. Nim 游戏(博弈论 - java)

Nim 游戏 Nim 游戏题目描述博弈论 上期经典算法 Nim 游戏 难度 - 简单 原题链接 - Nim游戏 题目描述 你和你的朋友&#xff0c;两个人一起玩 Nim 游戏&#xff1a; 桌子上有一堆石头。 你们轮流进行自己的回合&#xff0c; 你作为先手 。 每一回合&#xff0c;轮到的人拿掉 1 -…

MySQL 中 不等于 会过滤掉 Null 的问题

null值与任意值比较时都为fasle not in 、"!"、"not like"条件过滤都会过滤掉null值的数据 SELECT * from temp; SELECT * from temp where score not in (70); 返回null解决方法: SELECT * from temp where score not in (70) or score is null;SELECT…

OC调用Swift编写的framework

一、前言 随着swift趋向稳定&#xff0c;越来越多的公司都开始用swift来编写苹果相关的业务了&#xff0c;关于swift的利弊这里就不多说了。这里详细介绍OC调用swift编写的framework库的步骤 二、制作framework 1、新建项目&#xff0c;选择framework 2、填写framework的名称…