目 录CONTENT

文章目录

【DuckDB】开发DuckDB插件连接GaussDB/openGauss

DarkAthena
2026-07-25 / 0 评论 / 0 点赞 / 1 阅读 / 0 字

【DuckDB】开发DuckDB插件连接GaussDB/openGauss

背景

之前我有写过一篇使用DuckDB查询GaussDB里数据的文章【GaussDB】在duckdb中查询GaussDB的数据 ,部分大量数据的查询场景下,使用DuckDB来查询的性能的确优于直接在GaussDB里查询。但是之前这篇文章的方案有两个点绕不过去,即GaussDB的密码必须使用md5,以及要在DuckDB里设置成文本传输协议。后者还好说,多执行一条SQL而已;但是前者是服务端安全降级,部分安全等级较高的系统数据库是不允许使用md5密码的。

所以自然就想到,能不能基于DuckDB官方的postgres_scanner,改一个opengauss_scanner出来呢?

这要放在以前,调研开发测试还要花不少时间,但AI时代,有想法随时能造。

开发

本次使用Qoder的极致模型进行开发(虽然我早已退订qoder,但是最近官方一直免费在送credits,而且相同级别的任务,消耗比以前少多了,用得很爽)。

我打算写一个能在duckdb里查询openGauss数据库里数据的插件,参考duckdb的postgres_scanner插件,第一版本需要解决两个问题:1.openGauss的copy二进制协议流不标准,在原版postgres_scanner里必须先执行SET pg_use_text_protocol=true;,额外多执行了语句 2.openGauss的密码加密方式必须改成md5才能兼容postgres_scanner ,这会导致数据库安全降级。我想尽量能保持postgres_scanner的同步,而且编译插件时无需openGauss源码,最多引用一下openGauss已经编译好的libpq,你看下是否可以实现,给我计划。当前路径下我已经克隆了duckdb-postgres和openGauss的源码,并且已经放了一份已经编译好的libpq

后面交流的细节就不全部贴出,大概对话了有四十次,每次都是非常准确高效的。一个小时5次对话跑通,一天完善成型。

最终开发出来的代码核心为一个shell脚本,原版postgres_scanner作为该项目的子模块。原理是,postgres_scanner作为本项目的子模块,使用shell脚本去替换postgres_scanner中的代码,然后再编译。这样上游代码更新,或者切换DuckDB版本,我就不需要花时间去合并和解决冲突。当然如果后续哪次上游更新有了新的点没有被目前的替换逻辑踩中,就让AI去更新一下这个shell脚本就好了。至少我目前测了1.5.3和1.5.4都是可以跑通的(20260722已经适配了1.4.5 LTS版本)。

本地构建

本构建方案需要联网,获取指定版本duckdb及相关插件的源码(当然完整克隆指定版本代码后再离线构建也是可以的),而且环境本身必须要能构建DuckDB,目前DuckDB官方版本是用 GCC17 构建的,银河麒麟v10服务器版本默认的 GCC7 是构建不了的,需要手动配置高版本的GCC编译环境。我本地开发是用ubuntu 22 GCC11,能编译成功。编译好后再放到麒麟v10上使用也是可以的。

# 递归克隆
git clone --recursive https://github.com/Dark-Athena/duckdb-opengauss-scanner.git

# 放入libpq 
cd duckdb-opengauss-scanner
curl -LO https://opengauss.obs.cn-south-1.myhuaweicloud.com/6.0.5/openEuler20.03/x86/openGauss-Libpq-6.0.5-openEuler20.03-x86_64.tar.gz
mkdir -p libpq && tar -xzf openGauss-Libpq-6.0.5-openEuler20.03-x86_64.tar.gz -C libpq --strip-components=1

# 编译,成品在dist目录下
rm -rf duckdb-postgres/build dist 
./build_opengauss_scanner.sh --ninja

# 如果需要指定DuckDB版本,可通过--duckdb-version 指定
rm -rf duckdb-postgres/build dist
./build_opengauss_scanner.sh --duckdb-version v1.4.5 --ninja

使用演示

项目已提供预编译好的插件包,内置libpq,可直接下载解压使用(如果libpq版本升级,可尝试直接替换lib目录)。

[root@ky10-sp3 test_duckdb_gaussdb]# wget https://install.duckdb.org/v1.4.5/duckdb_cli
-linux-amd64.zip
--2026-07-22 13:24:23--  https://install.duckdb.org/v1.4.5/duckdb_cli-linux-amd64.zip
Resolving install.duckdb.org (install.duckdb.org)... 28.0.0.104, fc00::7c
Connecting to install.duckdb.org (install.duckdb.org)|28.0.0.104|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 19099102 (18M) [application/octet-stream]
Saving to: ‘duckdb_cli-linux-amd64.zip’

duckdb_cli-linux-amd6 100%[=======================>]  18.21M  6.52MB/s    in 2.8s

2026-07-22 13:24:27 (6.52 MB/s) - ‘duckdb_cli-linux-amd64.zip’ saved [19099102/19099102]

[root@ky10-sp3 test_duckdb_gaussdb]# wget https://github.com/Dark-Athena/duckdb-opengauss-scanner/releases/download/v0.0.1-beta/opengauss_scanner-gaussdb-linux_amd64-v1.4.5
.zip
--2026-07-22 13:24:49--  https://github.com/Dark-Athena/duckdb-opengauss-scanner/releases/download/v0.0.1-beta/opengauss_scanner-gaussdb-linux_amd64-v1.4.5.zip
Resolving github.com (github.com)... 28.0.0.13, fc00::e
Connecting to github.com (github.com)|28.0.0.13|:443... connected.
HTTP request sent, awaiting response... 302 Found
Location: https://release-assets.githubusercontent.com/github-production-release-asset/1306260979/0320b190-bda7-4d1d-b2d1-26ed81090cd9?sp=r&sv=2018-11-09&sr=b&spr=https&se=2026-07-22T06%3A18%3A13Z&rscd=attachment%3B+filename%3Dopengauss_scanner-gaussdb-linux_amd64-v1.4.5.zip&rsct=application%2Foctet-stream&skoid=96c2d410-5711-43a1-aedd-ab1947aa7ab0&sktid=398a6654-997b-47e9-b12b-9515b896b4de&skt=2026-07-22T05%3A17%3A53Z&ske=2026-07-22T06%3A18%3A13Z&sks=b&skv=2018-11-09&sig=By0WNTcykjXBEtyk0cRIkM2ByCA%2F1UE6uyAnK1vQIjA%3D&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmVsZWFzZS1hc3NldHMuZ2l0aHVidXNlcmNvbnRlbnQuY29tIiwia2V5Ijoia2V5MSIsImV4cCI6MTc4NDY5OTY5MCwibmJmIjoxNzg0Njk3ODkwLCJwYXRoIjoicmVsZWFzZWFzc2V0cHJvZHVjdGlvbi5ibG9iLmNvcmUud2luZG93cy5uZXQifQ.bUSPURfYdgvbqibBSBAaIhNOWezv5UxNAfkrxoHe-uI&response-content-disposition=attachment%3B%20filename%3Dopengauss_scanner-gaussdb-linux_amd64-v1.4.5.zip&response-content-type=application%2Foctet-stream [following]
--2026-07-22 13:24:50--  https://release-assets.githubusercontent.com/github-production-release-asset/1306260979/0320b190-bda7-4d1d-b2d1-26ed81090cd9?sp=r&sv=2018-11-09&sr=b&spr=https&se=2026-07-22T06%3A18%3A13Z&rscd=attachment%3B+filename%3Dopengauss_scanner-gaussdb-linux_amd64-v1.4.5.zip&rsct=application%2Foctet-stream&skoid=96c2d410-5711-43a1-aedd-ab1947aa7ab0&sktid=398a6654-997b-47e9-b12b-9515b896b4de&skt=2026-07-22T05%3A17%3A53Z&ske=2026-07-22T06%3A18%3A13Z&sks=b&skv=2018-11-09&sig=By0WNTcykjXBEtyk0cRIkM2ByCA%2F1UE6uyAnK1vQIjA%3D&jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmVsZWFzZS1hc3NldHMuZ2l0aHVidXNlcmNvbnRlbnQuY29tIiwia2V5Ijoia2V5MSIsImV4cCI6MTc4NDY5OTY5MCwibmJmIjoxNzg0Njk3ODkwLCJwYXRoIjoicmVsZWFzZWFzc2V0cHJvZHVjdGlvbi5ibG9iLmNvcmUud2luZG93cy5uZXQifQ.bUSPURfYdgvbqibBSBAaIhNOWezv5UxNAfkrxoHe-uI&response-content-disposition=attachment%3B%20filename%3Dopengauss_scanner-gaussdb-linux_amd64-v1.4.5.zip&response-content-type=application%2Foctet-stream
Resolving release-assets.githubusercontent.com (release-assets.githubusercontent.com)... 28.0.0.132, fc00::98
Connecting to release-assets.githubusercontent.com (release-assets.githubusercontent.com)|28.0.0.132|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 18367167 (18M) [application/octet-stream]
Saving to: ‘opengauss_scanner-gaussdb-linux_amd64-v1.4.5.zip’

opengauss_scanner-gau 100%[=======================>]  17.52M  5.16MB/s    in 3.4s

2026-07-22 13:24:55 (5.16 MB/s) - ‘opengauss_scanner-gaussdb-linux_amd64-v1.4.5.zip’ saved [18367167/18367167]

[root@ky10-sp3 test_duckdb_gaussdb]# ll
total 36592
-rw-r--r-- 1 root root 19099102 Jun 17 18:44 duckdb_cli-linux-amd64.zip
-rw-r--r-- 1 root root 18367167 Jul 22 11:00 opengauss_scanner-gaussdb-linux_amd64-v1.4.5.zip
[root@ky10-sp3 test_duckdb_gaussdb]# unzip duckdb_cli-linux-amd64.zip
Archive:  duckdb_cli-linux-amd64.zip
  inflating: duckdb
[root@ky10-sp3 test_duckdb_gaussdb]# unzip opengauss_scanner-gaussdb-linux_amd64-v1.4.5.zip
Archive:  opengauss_scanner-gaussdb-linux_amd64-v1.4.5.zip
   creating: lib/
  inflating: lib/libcrypto.so.1.1
  inflating: lib/libkrb5support.so.0
  inflating: lib/libgssrpc.so
  inflating: lib/libcjson.so.1
  inflating: lib/libkrb5support.so
  inflating: lib/libcjson.so.1.7.17
  inflating: lib/libgssapi_krb5.so.2
  inflating: lib/libpq.so.5
  inflating: lib/libpq.so.5.5
  inflating: lib/libcom_err.so.3
  inflating: lib/libconfig.so
  inflating: lib/libcjson.so
  inflating: lib/libconfig.so.4
  inflating: lib/libk5crypto.so.3
  inflating: lib/libkrb5support.so.0.1
  inflating: lib/libgssrpc.so.4
  inflating: lib/libkrb5.so
  inflating: lib/libssl.so
  inflating: lib/libcrypto.so
  inflating: lib/libssl.so.1.1
  inflating: lib/libcom_err.so.3.0
  inflating: lib/libpgport_tool.so
  inflating: lib/libkrb5.so.3.3
  inflating: lib/libpgport_tool.so.1
  inflating: lib/libk5crypto.so.3.1
  inflating: lib/libgssapi_krb5.so
  inflating: lib/libgssapi_krb5.so.2.2
  inflating: lib/libgssrpc.so.4.2
  inflating: lib/libkrb5.so.3
  inflating: lib/libk5crypto.so
  inflating: lib/libcom_err.so
  inflating: lib/libpq.so
  inflating: opengauss_scanner.duckdb_extension
  inflating: USAGE.md
[root@ky10-sp3 test_duckdb_gaussdb]# ll
total 124656
-rwxr-xr-x 1 root root 56804824 Jun 15 15:51 duckdb
-rw-r--r-- 1 root root 19099102 Jun 17 18:44 duckdb_cli-linux-amd64.zip
drwxr-xr-x 2 root root     4096 Jul 22 10:59 lib
-rw-r--r-- 1 root root 33360678 Jul 22 10:59 opengauss_scanner.duckdb_extension
-rw-r--r-- 1 root root 18367167 Jul 22 11:00 opengauss_scanner-gaussdb-linux_amd64-v1.4.5.zip
-rw-r--r-- 1 root root     1561 Jul 22 10:59 USAGE.md
[root@ky10-sp3 test_duckdb_gaussdb]# ./duckdb -unsigned
DuckDB v1.4.5 (Andium) f31be57c18
Enter ".help" for usage hints.
D load 'opengauss_scanner.duckdb_extension';
D ATTACH 'host=192.168.163.140 port=8000 dbname=postgres user=root password=Gaussdb@123 connect_timeout=10' AS og (TYPE opengauss);
D select datname from og.pg_catalog.pg_database;
┌───────────┐
│  datname  │
│  varchar  │
├───────────┤
│ templatea │
│ template1 │
│ templatem │
│ template0 │
│ postgres  │
└───────────┘

注意事项

需要注意的是,目前该插件仅仅只是解决了官方版本postgres_scanner插件密码认证以及二进制文本协议的问题,没有对GaussDB/openGauss做额外的适配,比如GaussDB/openGauss相对于原生PG多出来的一些数据类型能否正常查询,我没去管。

另外,这个插件也没签名,所以启动DuckDB时要加-unsigned来允许加载未签名的插件,其他开发语言参考项目demos目录下的示例,配置allow_unsigned_extensions参数。

项目已添加流水线配置(commit不自动触发,打tag自动触发),支持构建linux_arm64/linux_amd64两个平台上的连接openGauss和GaussDB插件,一共4个版本。fork后可以自己在action里选择需要的DuckDB版本来进行构建。

项目地址: https://github.com/Dark-Athena/duckdb-opengauss-scanner

最后贴一下项目readme


duckdb-opengauss-scanner

基于 duckdb-postgres(postgres_scanner) 构建面向
openGauss 家族(openGauss / MogDB / VastBase / PanWeiDB / GaussDB) 的 DuckDB 可加载扩展。

相比原版 postgres_scanner,本扩展解决三个关键差异:

  • 免手动 SET 协议:openGauss 的 COPY 二进制流与标准 PostgreSQL 不完全兼容。扩展默认启用
    TEXT 协议(opengauss_use_text_protocol=true),无需每次连接后手动 SET
  • 原生 sha256 认证:openGauss 家族默认口令加密为 sha256。原版需把服务端降级为 md5 才能连接;
    本扩展链接 openGauss 自带的 libpq,直接支持 sha256,无需安全降级
  • 可与官方 postgres_scanner 共存:所有对外标识符全量改名为 opengauss 前缀(TYPE opengauss
    opengauss_* 函数、secret 类型 opengauss),与官方 postgres_scanner 完全不重叠,可在同一
    DuckDB 实例内同时加载、分别连接原生 PostgreSQL 与 openGauss/GaussDB。

一、设计原则

  1. 不改上游源码:构建前对少量文件打临时补丁,构建结束(含失败/中断)后由 trap 自动还原
    保证 duckdb-postgres 的 git 工作区始终干净。
  2. 无需 openGauss 源码:只链接指定目录下 openGauss 已编译好的 libpq(.so)
  3. 可移植 bundle:产物扩展内置 DT_RPATH=$ORIGIN/lib,运行期从扩展同级的 lib/ 子目录
    解析 libpq 及其 openGauss 专属 krb5/gss/crypto 依赖,与启动 DuckDB 的宿主语言
    (Java / C / Python / CLI) 及当前工作目录无关。

二、前置依赖

依赖说明
cmakemakeg++编译工具链(C++17)。GCC 必须 ≥ 8(推荐 11+),见第十一节。GCC 7 会在链接期报 undefined reference to std::allocator<...>::allocator()
ninja可选,指定 --ninja 时需要
python3仅用于给上游源码打补丁(多行/正则/JSON 编辑 + fail-fast 校验),几乎所有环境自带
libssl-dev编译时需要 OpenSSL 开发头文件
openGauss libpq使用者自备(不随本仓库分发),含 include/libpq-fe.hlib/libpq.so*,构建时用 --libpq-dir 指定
duckdb-postgres 子模块本仓库以子模块形式引用,其内部还嵌套 duckdb 子模块,需递归拉取

获取源码(含嵌套子模块)

duckdb-postgres 是本仓库的子模块,且其内部还嵌套 duckdb 子模块,务必递归拉取:

# 新克隆
git clone --recursive https://github.com/Dark-Athena/duckdb-opengauss-scanner.git

# 或已克隆但未拉子模块
git submodule update --init --recursive

openGauss libpq 不在仓库内,请自备后放到 ./libpq(默认)或用 --libpq-dir 指定,目录结构见下节。

⚠️ 内存提示:DuckDB 采用 unity build,单个编译单元约需 2GB 内存。若机器内存 ≤ 4GB,
请用 --jobs 2(甚至 --jobs 1),否则可能触发 OOM killer(Killed signal terminated program cc1plus)。


三、libpq 目录结构

下载 openGauss libpq()

官方预编译 libpq 下载(按 CPU 架构选择):

架构下载链接
x86_64https://opengauss.obs.cn-south-1.myhuaweicloud.com/6.0.5/openEuler20.03/x86/openGauss-Libpq-6.0.5-openEuler20.03-x86_64.tar.gz
aarch64https://opengauss.obs.cn-south-1.myhuaweicloud.com/6.0.5/openEuler20.03/arm/openGauss-Libpq-6.0.5-openEuler20.03-aarch64.tar.gz

下载后解压,使解压结果符合下方目录结构,再用 --libpq-dir 指向该目录(默认 ./libpq):

# 以 x86_64 为例
curl -LO https://opengauss.obs.cn-south-1.myhuaweicloud.com/6.0.5/openEuler20.03/x86/openGauss-Libpq-6.0.5-openEuler20.03-x86_64.tar.gz
mkdir -p libpq && tar -xzf openGauss-Libpq-6.0.5-openEuler20.03-x86_64.tar.gz -C libpq --strip-components=1
# 校验: 应存在 libpq/include/libpq-fe.h 与 libpq/lib/libpq.so*

解压后若 include/lib/ 不在 libpq/ 顶层,请自行调整 --strip-components 或移动目录,
确保最终形如下方结构。

目录结构要求

--libpq-dir 指向的目录需形如:

libpq/
├── include/
│   └── libpq-fe.h          # 头文件(校验其存在)
└── lib/
    ├── libpq.so / libpq.so.5 / libpq.so.5.5
    ├── libssl.so.3 / libcrypto.so.3
    └── lib*_gauss.so*      # openGauss 专属 krb5 / gss / com_err 等

如果连接华为GaussDB,建议使用华为官方提供的GaussDB的libpq,连接其他openGauss发行版也均建议使用发行厂家单独提供的libpq


四、使用方法

基本用法(全部使用默认路径)

./build_opengauss_scanner.sh

默认:libpq-dir=./libpqduckdb-postgres=./duckdb-postgresoutput=./dist、并发 = nproc

常用示例

# 低内存机器:限制并发 + 用 ninja(失败时可一次性枚举全部编译错误)
./build_opengauss_scanner.sh --ninja --jobs 2

# 指定 libpq 与输出目录
./build_opengauss_scanner.sh --libpq-dir /opt/gauss/libpq --output /tmp/og_dist

# 调试版
./build_opengauss_scanner.sh --debug

参数说明

参数默认值说明
--libpq-dir DIR./libpqopenGauss libpq 目录(含 include/lib/)
--duckdb-postgres DIR./duckdb-postgrespostgres_scanner 源码目录(含 duckdb 子模块)
--output DIR./dist产物输出目录
--jobs N / -j Nnproc编译并发数
--debug关(release)构建调试版本
--ninja关(make)使用 ninja 生成器
-h / --help显示帮助

五、构建流程

脚本分三个阶段,一条命令完成"打补丁 → 构建 → 自动还原 → 打包 bundle":

  1. 阶段 1 — 打临时补丁(结束后自动还原)
    • Makefile / extension_config.cmake / CMakeLists.txt:扩展改名为 opengauss_scanner
    • CMakeLists.txt:绕过 find_package(PostgreSQL),改指向 openGauss libpq;注入
      --disable-new-dtags(老式 DT_RPATH 以传递给二级依赖) 与 $ORIGIN/lib rpath
    • postgres_extension.cppopengauss_use_text_protocol 默认 false→true;扩展入口宏改名
      (使入口符号变为 opengauss_scanner_duckdb_cpp_init);secret 类型/函数、存储扩展键、
      per-connection state 键均改为独立命名
    • 全量重命名(与官方 postgres_scanner 同实例共存):所有对外函数 postgres_*/pg_*
      opengauss_*(scan/scan_pushdown/query/attach/execute/binary/configure_pool/hstore_* 等),
      TYPE postgres_scanneropengauss,secret 类型 postgres/rdsopengauss/opengauss_rds
      开关 pg_use_text_protocolopengauss_use_text_protocol,并同步内部按名调用/判断处
    • postgres_oauth.cpp:替换为 no-op 桩(openGauss libpq 无新版 OAuth API)
    • postgres_catalog.cpp / postgres_secret_storage.cppreturn xreturn std::move(x)
      (GCC11 + C++17 具名局部返回值隐式移动兼容)
    • vcpkg.json:移除 libpq 依赖(本构建不走 vcpkg)
  2. 阶段 2 — 构建:链接 openGauss libpq 编译扩展。失败且启用 --ninja 时,会用
    ninja -k 0 一次性枚举全部编译错误便于定位。
  3. 阶段 3 — 打包 bundle:收集扩展与运行时依赖到输出目录,生成 USAGE.md,并校验 rpath。

六、产物

构建成功后 dist/(或 --output 指定目录)结构:

dist/
├── opengauss_scanner.duckdb_extension   # 扩展本体
├── USAGE.md                             # 使用说明(自动生成)
└── lib/                                 # 运行时依赖(保留 libpq/lib 原目录结构与软链)
    ├── libpq.so*  libssl.so.3  libcrypto.so.3
    └── lib*_gauss.so*

📦 整体移动dist/ 可整体拷贝到其它机器/路径使用。移动时必须保持扩展与 lib/ 的相对位置
(rpath 是 $ORIGIN/lib),不要把扩展单独拆出去。


七、使用扩展

-- 未签名扩展需 CLI 加 -unsigned 启动,或启动时开启 allow_unsigned_extensions
LOAD 'dist/opengauss_scanner.duckdb_extension';

-- 连接 openGauss 家族数据库(sha256 认证,无需 md5 降级)。
-- 注意: 本扩展已全量改名,ATTACH 使用 TYPE opengauss(不再是 TYPE postgres)。
ATTACH 'host=127.0.0.1 port=5432 dbname=postgres user=xxx password=xxx' AS og (TYPE opengauss);

-- 默认已启用 TEXT 协议(opengauss_use_text_protocol=true),直接查询即可
SELECT * FROM og.public.your_table LIMIT 10;

-- 透传 SQL 到远端执行, 用 opengauss_query(对应官方的 postgres_query)
SELECT * FROM opengauss_query('og', 'SELECT version()');

🔀 与官方 postgres_scanner 同实例共存:本扩展的所有对外标识符都改成了 opengauss 前缀
(TYPE opengauss、函数 opengauss_query/opengauss_scan/opengauss_attach/…、secret 类型
opengauss、开关 opengauss_use_text_protocol),与官方 postgres_scanner(TYPE postgres
postgres_*)完全不重叠。因此可在同一个 DuckDB 实例里同时 LOAD 两者,分别 ATTACH 原生
PostgreSQL(TYPE postgres)与 openGauss/GaussDB(TYPE opengauss),互不干扰。

📦 各语言客户端示例:CLI / Python / C / Node.js / ODBC / R / Rust / Java 如何"开启允许未签名扩展
LOADATTACH 查询"的可运行 demo,见 demos/。关键点:allow_unsigned_extensions
是启动期设置,必须在建连/建库那一刻通过 config/连接属性/-unsigned 给出,连上后再 SET 会报错。


八、功能自测

仓库提供 test_opengauss_scanner.sh,逐项验证加载、连接、协议、家族探测、元数据与原生扫描,
输出 PASS/FAIL 汇总(全通过退出码 0,便于接入 CI):

# 默认参数
./test_opengauss_scanner.sh

# 指定连接信息
./test_opengauss_scanner.sh --host 127.0.0.1 --port 5432 --user gaussdb --password 'Xxx@123'

./test_opengauss_scanner.sh -h   # 查看全部选项

九、常见问题

现象原因 / 处理
Killed signal terminated program cc1plus内存不足触发 OOM。降低并发:--jobs 2--jobs 1
duckdb 子模块未拉取执行 git submodule update --init --recursive
找不到 .../libpq-fe.h--libpq-dir 指向的目录缺少 include/libpq-fe.h,检查 libpq 路径。
构建失败缺 OpenSSL安装 libssl-dev(Debian/Ubuntu)。
did not contain the expected entrypoint扩展名与入口符号不匹配;本脚本已自动处理,如自行改名需同步入口宏。

十、指定 DuckDB 版本构建

要编译哪个/哪些 DuckDB 版本, 由仓库根的 duckdb_versions.json 决定 —— 这是唯一事实源

{
  "default": "v1.5.4",                 // 未指定版本时的默认(普通/本地构建)
  "versions": {
    // DuckDB 版本 tag  ->  duckdb-postgres 的官方 pin 完整 commit SHA
    // 该 SHA 取自 duckdb/duckdb 在该版本 tag 冻结的
    //   .github/config/extensions/postgres_scanner.cmake 的 GIT_TAG
    // (可用 scripts/resolve_pg_ref.sh <版本> 解析)。
    "v1.5.4": "8f813f9b9c9e52a9074a050a0be60f49160a6baa",
    "v1.5.3": "6b2b12cad3afef61e8a4637e714e8a88895fed1a",
    "v1.4.5": "b9fce43bc5d36bc6db70844f28b7b146e756eb22"
  }
}

为什么用官方 pin SHA(而不是分支/版本号/Bump 提交):duckdb-postgres 不打 release tag。
我们统一采用官方口径 —— 即 duckdb/duckdb 主仓库在各版本 tag 里冻结的 postgres_scanner
源码 commit。这是对任何版本(含分支已被删的 EOL 版本, 如 v1.4.5)都通用的权威来源。

注意:官方 pin 自带的嵌套 duckdb 子模块可能滞后目标版本(例如 v1.5.4 的 pin 内嵌 v1.5.3)。
构建时由 scripts/select_duckdb.sh 把嵌套 duckdb 强制覆盖到目标版本 tag —— 等价于官方
发布流程里的 make set_duckdb_version。因此"指定 DuckDB 版本"最终决定实际编译哪个 DuckDB。

在 CI 里构建指定版本(推荐)

到 GitHub Actions 手动运行 Build & Release(workflow_dispatch), 选 duckdb_version:

  • all —— 构建清单里全部版本(打 v* tag 发布时也是这个行为)
  • default —— 只构建清单 default 指定的版本
  • 指定版本(如 v1.5.4)—— 只构建该版本

CI 会调用 scripts/select_duckdb.sh <版本> <官方pin>duckdb-postgres 切到清单登记的官方 pin、
把嵌套 duckdb 强制覆盖到目标版本, 并以 OVERRIDE_GIT_DESCRIBE=<版本> 把扩展正确戳成该 DuckDB
版本
, 产物名带版本号(见第十二节)。

新增一个 DuckDB 版本(维护步骤)

scripts/resolve_pg_ref.sh 解析该版本的官方 pin(读 duckdb/duckdb 对应 tag 冻结的
postgres_scanner.cmakeGIT_TAG, 对 EOL 版本同样适用):

scripts/resolve_pg_ref.sh v1.5.5      # -> stdout 打印完整 40 位 SHA; stderr 打印核对信息

然后改两处(仅这两处):

  1. duckdb_versions.jsonversions 里加一行:"v1.5.5": "<完整SHA>"(需要的话改 default)。
  2. .github/workflows/build.ymlworkflow_dispatch.inputs.duckdb_version.options 加一项 v1.5.5
    (仅为下拉菜单便利;实际解析以清单为准)。

大版本(如 1.5 → 1.6)时, 我们对 duckdb-postgres 打的 rebrand/sha256/TEXT 补丁锚点可能
变化, 首次构建需留意补丁是否踩空。补丁点集中在 Makefile / extension_config.cmake /
CMakeLists.txt 及少数 src/*.cpp

本地构建指定版本

最省事是把版本号直接交给构建脚本 —— 它会调用 scripts/select_duckdb.sh 走官方口径切换
(切到官方 pin + 覆盖嵌套 duckdb 到目标版本), 并自动以该版本作为版本戳:

rm -rf duckdb-postgres/build dist                        # 切版本前务必清理旧产物
./build_opengauss_scanner.sh --duckdb-version v1.4.5 --ninja

--duckdb-version 对分支已删的 EOL 版本(如 v1.4.5)同样有效 —— 只要该版本已在
duckdb_versions.json 登记。省略该参数时, 脚本直接构建 duckdb-postgres当前 checkout,
并从嵌套 duckdbgit describe --tags 自动推导版本戳, 无需手动设 OVERRIDE_GIT_DESCRIBE

也可先单独切换再构建(等价, 便于排查):

scripts/select_duckdb.sh v1.4.5      # 官方口径切换(幂等; 已在目标状态则跳过网络操作)
rm -rf duckdb-postgres/build dist
./build_opengauss_scanner.sh --ninja
# 如需强制指定版本戳: OVERRIDE_GIT_DESCRIBE=v1.4.5 ./build_opengauss_scanner.sh ...

两个必须注意的点

  1. 加载扩展的 DuckDB 必须版本一致:扩展元数据绑定了构建时的 duckdb 版本, 版本不符 LOAD
    会被拒(... was built for DuckDB version 'vX' ...;若戳成 v0.0.1 则说明版本戳未生效)。
    最省事是用构建同时产出的 CLI duckdb-postgres/build/release/duckdb(天然匹配, 测试脚本默认
    就用它);用外部 duckdb 需下载同一版本
  2. 切换版本后清理旧产物再编译:rm -rf duckdb-postgres/build dist

1.4.x (LTS) 与 1.5.x 的架构差异

v1.4.5 是 DuckDB 官网当前的 LTS 版本, 本仓库已完整支持。需要注意 duckdb-postgres
在 1.4.x 与 1.5.x 用了两套完全不同的 libpq 获取方式, 构建脚本用 特性探测(feature-probing,按锚点/文件存在与否, 而非硬编码版本号) 自动选对补丁, 因此 --duckdb-version 对两代都适用:

1.5.x1.4.x (LTS)
libpq 来源find_package(PostgreSQL REQUIRED) 链接预编译 libpq下载 PostgreSQL 15.13 源码 + ./configure 把 PG 官方 libpq 静态编进扩展
本仓库补丁替换 find_package(PostgreSQL) 为指向 openGauss libpq 的 IMPORTED target移除"下载/编译 PG 源码"逻辑, 改链外部 openGauss libpq(OPENSSL_USE_STATIC_LIBS 也随之改 FALSE)
secret/storage 注册分散在 postgres_secrets.cpp 等, 用 StorageExtension::Register(...)集中在 postgres_extension.cpp, 用 config.storage_extensions[...]
缺失的文件/特性齐全postgres_oauth/aws/hstore/logging/configure_pool/secret_storage, 无 read_postgres_binary/RemoteExecute(相关补丁"存在才打", 自动跳过)

无论哪代, 最终都只链接外部 openGauss libpq —— openGauss 家族的 sha256 认证依赖其自带
libpq, PostgreSQL 官方 libpq 不识别, 故 1.4.x 也必须移除内嵌的 PG libpq。


十一、DuckDB 官方预编译版本的编译依赖链

本项目产物是 DuckDB 可加载扩展,最终要被官方发行的 DuckDB 加载运行。官方的 Linux 预编译
二进制(含 CLI 与扩展)全部在固定的容器工具链里构建,其配置直接来自
duckdb-postgres/extension-ci-tools/docker/*/Dockerfile(由 duckdb 发版 CI 调用)。要让自编译的
扩展与官方运行时二进制/ABI 匹配,本地编译环境应尽量向这条链看齐。

官方各平台工具链一览

平台 (DUCKDB_PLATFORM)基础镜像发行版编译器glibc / libc 基线
linux_amd64quay.io/pypa/manylinux_2_28_x86_64AlmaLinux 8GCC(gcc-toolset),当前 GCC 14glibc ≥ 2.28
linux_arm64quay.io/pypa/manylinux_2_28_aarch64AlmaLinux 8GCC(gcc-toolset),当前 GCC 14glibc ≥ 2.28
linux_amd64_muslalpine:3.22AlpineGCC / clang19musl libc
linux_arm64_muslalpine:*(同上)AlpineGCC / clang19musl libc

补充要点(来自 Dockerfile 与 manylinux 官方说明):

  • glibc 基线 2.28manylinux_2_28 保证产物可在 glibc ≥ 2.28 的发行版运行
    (Debian 10+ / Ubuntu 18.10+ / CentOS·RHEL 8+ / Kylin V10)。这是"最低运行门槛",
    本地 glibc 等于或高于 2.28 都可以。
  • 编译器为较新的 GCC:manylinux 镜像随时间升级其 gcc-toolset(历史上 11→12→13,当前为
    GCC 14)。官方并不用某个精确的 GCC 小版本,但都是 GCC 8 以上的现代版本
  • 构建系统:CMake(官方镜像用 4.0.2) + Ninja(GEN=ninja) + ccache;vcpkg 提供第三方依赖。
    本项目不强制这些(用系统 CMake≥3.5、Makefiles 或 Ninja 均可),仅编译器版本是硬约束。

对本地/自编译环境的要求

项目要求说明
GCC≥ 8,推荐 11+DuckDB 源码是 C++17。GCC 7 会失败:链接期报 undefined reference to std::allocator<duckdb::Value>::allocator() —— 这是 GCC 7 libstdc++ 对部分模板类型未内联发射 allocator 默认构造函数的已知缺陷,GCC 8 已修复。要贴近官方可用 GCC 11+。
glibc≥ 2.28与官方 manylinux_2_28 一致即可;低于 2.28 也许能自编译,但产物无法在官方运行时环境保证兼容。
CMake≥ 3.5duckdb v1.5.3 声明 cmake_minimum_required(3.5...3.29);CMAKE_CXX_STANDARD=11,实际按源码需要拉到 C++17。
clang亦可官方 musl 镜像用 clang19;若本地用 clang,版本需完整支持 C++17。

💡 为什么 Kylin V10 / 老 CentOS 8 上默认 gcc 7.3.0 编不过:这类系统 glibc 2.28 达标,
自带 GCC 7 过老。解决办法是装一个更新的 GCC 后再构建,例如:

# openEuler / Kylin V10(dnf/yum):安装 gcc-toolset
sudo dnf install -y gcc-toolset-11-gcc gcc-toolset-11-gcc-c++
source /opt/rh/gcc-toolset-11/enable   # 仅当前 shell 生效
gcc --version                          # 确认 >= 8(此处为 11)
# 然后照常运行构建脚本
./build_opengauss_scanner.sh --jobs 8

若源不含 gcc-toolset,可从源码编译 GCC 11+ 或改用具备新版 GCC 的构建机;
最贴近官方的做法是直接在 manylinux_2_28 容器内构建。


十二、GitHub Actions 自动化构建与发布

仓库内置 .github/workflows/build.yml,按 DuckDB 官方构建方案(在
quay.io/pypa/manylinux_2_28_{x86_64,aarch64} 容器内, gcc-toolset / glibc 2.28)自动产出
可分发压缩包。产物 = (清单里选中的 DuckDB 版本数) × 2 variant × 2 platform, 命名带版本号
opengauss_scanner-<variant>-<platform>-<duckdb_version>.zip:

variantplatform压缩包(以 v1.5.4 为例)使用的 libpq
openGausslinux_amd64opengauss_scanner-opengauss-linux_amd64-v1.5.4.zipopenGauss 官方预编译 libpq(x86_64)
openGausslinux_arm64opengauss_scanner-opengauss-linux_arm64-v1.5.4.zipopenGauss 官方预编译 libpq(aarch64)
GaussDBlinux_amd64opengauss_scanner-gaussdb-linux_amd64-v1.5.4.zip华为 GaussDB 驱动包 Kylin V10 / X86_64 版 libpq
GaussDBlinux_arm64opengauss_scanner-gaussdb-linux_arm64-v1.5.4.zip华为 GaussDB 驱动包 Kylin V10 / arm_64 版 libpq
  • 构建哪些 DuckDB 版本:由 duckdb_versions.json + 触发时的选择决定(见第十节)。
  • openGauss libpq:直接下载第三节给出的官方 tar.gz。
  • GaussDB libpq:参照华为
    install_gaussdb_driver.sh
    的方式下载 GaussDB_driver.zip,但只取 Centralized/Kylinv10_<ARCH>/ 里的 libpq
  • 自动测试:在 linux_amd64linux_arm64 上各自拉起
    opengauss docker
    (opengauss/opengauss-server:latest 为 amd64/arm64 多架构镜像, 各 runner 自动拉对应架构),用本次同版本产出的 DuckDB CLI
    LOAD + ATTACH (TYPE opengauss) + 查询的冒烟测试(两种 variant 都测:GaussDB 版扩展同样以
    sha256 连接 openGauss 服务端)。
  • 发布:推送 v* tag 时,自动构建清单里全部版本并把压缩包挂到 GitHub Release。

触发方式(普通 push / PR 不再自动构建, 完全手动控制何时编译):

  • workflow_dispatch(手动):选 duckdb_version = all / default / 指定版本。
  • v* tag:构建清单全部版本并发布 Release。

arm64 构建与测试均在 GitHub 托管的 ubuntu-24.04-arm 原生 runner 上进行(非 QEMU 模拟),
与 amd64 同等覆盖(构建 + 加载/连接/查询冒烟测试)。


0
博主关闭了所有页面的评论