一、插件的基本组成
在 He3DB 中,插件(或称扩展)是一种可扩展的机制,允许用户增加数据库的功能。每个插件的基本组成部分如下:
(1)控制文件(.control 文件):
位置:通常位于 $PGSHARE/extension/ 目录中。
内容:控制文件定义了插件的元数据,包括名称、默认版本、兼容版本、SQL 脚本路径等。它的结构是键值对格式,常见字段包括:
name:插件名称。
default_version:默认版本号。
comment:描述信息。
relocatable:是否可以重新定位,即插件是否可以安装到不同的 schema 中。
requires:插件依赖的其他插件列表。
module_pathname:共享库文件的路径。
schema:安装插件时默认的 schema。
(2)SQL 脚本文件:
位置:通常位于 $PGSHARE/extension/ 目录中,文件名通常为 extension–version.sql 。
内容:SQL 脚本文件定义了插件在数据库中的对象,例如函数、视图、数据类型、操作符等。这些 SQL 脚本在安装插件时会被执行。
(3)源码文件(.c).c 文件包含扩展的实现代码,通常用 C 或 C++ 编写。它定义了扩展中的函数、操作符等。
(4)Makefile 文件Makefile 文件用于定义如何编译和链接扩展。它通常包括编译选项、目标文件和链接规则。
二、CREATE EXTENSION 命令的执行流程
CREATE EXTENSION 命令用于安装和初始化插件。以下是该命令的详细执行流程:
-
语法解析与检查:He3DB 解析 CREATE EXTENSION 命令,检查插件名称、版本和选项是否合法。如果指定了 SCHEMA选项,系统会验证该 schema 是否存在。
-
检查插件是否已存在:系统查询 pg_extension 表,检查插件是否已安装。如果插件已存在,系统将返回一个错误(除非使用 IF NOT EXISTS 选项)。
-
读取控制文件:在 pg_available_extensions 目录中搜索与插件名称匹配的 .control
文件,并读取其中定义的元数据。系统检查 default_version字段以确定要安装的插件版本。如果用户未指定版本,系统使用默认版本。 -
检查依赖关系:根据控制文件中的 requires 字段,系统检查所有依赖插件是否已经安装。如果依赖的插件未安装,系统将返回一个错误。系统还会检查插件是否可以重新定位(relocatable),如果插件不可重新定位但指定了 SCHEMA 选项,则会返回错误。
-
加载共享库:如果插件需要共享库(即 .so 文件), 会通过 module_pathname 加载该库。 加载时,系统会调用共享库中的_PG_init() 函数(如果存在)进行初始化。
-
执行 SQL 脚本: 执行与插件版本对应的 SQL 脚本文件,以创建和初始化插件的数据库对象。 这些脚本文件可以包含任何有效的 SQL语句,如创建函数、数据类型、视图等。
-
记录插件信息:系统在 pg_extension 表中记录插件的安装信息,包括名称、版本、安装 schema、依赖关系等。如果插件的schema 被更改,系统会更新 pg_extension 表中的相关信息。
-
插件初始化:某些插件在安装过程中可能需要执行自定义的初始化步骤,这通常通过共享库中的数或 SQL 脚本来完成。
-
返回结果:安装成功后,CREATE EXTENSION 命令会返回一个成功消息,表明插件已正确安装并可以使用
三、插件的使用和管理
1.使用插件:
在 He3DB 中,插件(扩展)安装后可以直接使用。例如,假设我们安装了前述的 my_extension 扩展:
– 安装扩展
CREATE EXTENSION my_extension;
– 使用扩展中的函数
SELECT my_function(10);
2.管理插件:
查看已安装扩展
SELECT * FROM pg_available_extensions;
卸载扩展
DROP EXTENSION my_extension;
更新扩展
更新扩展通常涉及到重新编译扩展并更新版本号。例如,修改 my_extension.control 和 .sql 文件后,执行:
ALTER EXTENSION my_extension UPDATE TO '1.1';
四、使用示例(C++ 函数使用案例)
- 编写 C++ 函数
示例:my_cpp_extension.cpp
#include "postgres.h"
#include "fmgr.h"
#ifdef PG_MODULE_MAGIC
PG_MODULE_MAGIC;
#endif
extern "C" {
PG_FUNCTION_INFO_V1(my_cpp_function);
Datum
my_cpp_function(PG_FUNCTION_ARGS)
{
int32 arg = PG_GETARG_INT32(0);
PG_RETURN_INT32(arg * 2);
}
}
2.编写对应的 SQL 文件
CREATE FUNCTION my_cpp_function(INTEGER) RETURNS INTEGER AS 'MODULE_PATHNAME', 'my_cpp_function'
LANGUAGE C;
- 编写 Makefile
MODULES = my_cpp_extension
EXTENSION = my_cpp_extension
DATA = my_cpp_extension--1.0.sql
PG_CONFIG = pg_config
PG_CXX = g++
CXXFLAGS += -I$(shell $(PG_CONFIG) --includedir-server)
LDFLAGS = -L$(shell $(PG_CONFIG) --libdir)
LIBS = -lpq
OBJS = my_cpp_extension.o
my_cpp_extension.o: my_cpp_extension.cpp
$(PG_CXX) $(CXXFLAGS) -fPIC -c -o $@ $<
my_cpp_extension.so: $(OBJS)
$(PG_CXX) $(LDFLAGS) -shared -o $@ $^ $(LIBS)
PGXS := $(shell $(PG_CONFIG) --pgxs)
include $(PGXS)
- 编写.control文件
# my_extension.control
comment = 'An example PostgreSQL extension'
default_version = '1.0'
module_pathname = '$libdir/my_extension'
relocatable = true
将 .control 文件放在扩展的目录中,与其他文件(如 .sql、.c、Makefile)同级。
编译和安装扩展:在 PostgreSQL 数据目录中运行 make 和 make install,编译扩展并将其安装到 PostgreSQL 的扩展目录中。
make
make install
在 He3DB 中使用
CREATE EXTENSION my_cpp_extension;
SELECT my_cpp_function(5);
作者介绍
张杰,移动云数据库工程师,负责云原生数据库He3DB的研发。