OpenGauss内置函数初始化与查询全解析

📅 2026/7/13 2:23:00 👁️ 阅读次数 📝 编程学习
OpenGauss内置函数初始化与查询全解析

1. initdb 时写入 pg_proc 的代码
builtin_funcs.ini 不是运行时读取的文本文件,而是通过 #include 在编译时被预处理器内联到 C++ 源码中(src/common/backend/catalog/pg_builtin_proc.cpp),生成 FuncGroup g_func_groups[] 数组。 t

写入 pg_proc 的核心代码在 src/common/backend/utils/cache/catcache.cpp:

- InsertBuiltinFuncInBootstrap()(约第 2495 行):遍历 g_func_groups[],对每个 Builtin_func 调用 CreateHeapTuple4BuiltinFunc() 构建 HeapTuple,然后通过
simple_heap_insert() 直接插入到 bootstrap 模式的 pg_proc 关系描述符中。
- 这个函数在 src/gausskernel/bootstrap/bootparse.y 中,当创建 pg_proc 关系后被调用(约第 250 行)。
- CreateHeapTuple4BuiltinFunc()(约第 1834 行)负责将 Builtin_func 结构体的各个字段(参数类型、返回值、语言ID、权限等)组装成符合 pg_proc 系统表布局的
HeapTuple。

2. 查询时是否直接使用全局变量

查询时有两条路径:

快速路径(按 OID 查找)—— 直接用全局变量,跳过 pg_proc 表:
- fmgr.cpp 中的 fmgr_isbuiltin() 调用 SearchBuiltinFuncByOid(),从 oidHash 哈希表中直接查到 Builtin_func 指针
- 如果命中,fmgr_info_cxt_security() 直接将 fn_addr 指向 C 函数地址,不查询 pg_proc 物理表

慢速路径(按名称+参数查找)—— 缓存未命中时用全局变量动态构造:
- 当系统缓存 SearchSysCache1(PROCNAMEARGSNSP, ...) 未命中时,SearchCatCacheListMiss() 会调用 SearchBuiltinProcCacheList()
- 该函数通过 nameHash 哈希表找到匹配的 Builtin_func,再用 CreateHeapTuple4BuiltinFunc() 动态构建一个 HeapTuple 返回
- 注意这里构建的 HeapTuple 和 bootstrap 阶段 simple_heap_insert 写入磁盘的物理 pg_proc 数据是共存的

整体流程:

builtin_funcs.ini
└─ #include 编译时内联 ─► g_func_groups[] / nameHash / oidHash

├─ initBuiltinFuncs() 进程启动时初始化哈希表

├─ Bootstrap 阶段 ─► InsertBuiltinFuncInBootstrap() ─► simple_heap_insert(pg_proc)

└─ 查询阶段
├─ fmgr_isbuiltin(oid) ─► oidHash 直接查 ─► 返回 fn_addr(不走 pg_proc 表)
└─ 按名缓存未命中 ─► nameHash 查 ─► CreateHeapTuple4BuiltinFunc() 动态构造 Tuple