当前位置: 首页 > news >正文

TimescaleDB的Cross-Module Function机制

函数映射的三层结构

SQL 层: compress_chunk(sql) → 'ts_compress_chunk'(C函数名) ↓ src/cross_module_fn.c: ts_compress_chunk() → 代理/跳板函数 (Apache License) ↓ ts_cm_functions->compress_chunk(fcinfo) ↓ tsl/src/init.c: .compress_chunk = tsl_compress_chunk ← 真正的函数指针赋值 (TSL License) ↓ tsl/src/compression/api.c: tsl_compress_chunk() ← 真正的实现

第一步:SQL 声明 → C 函数名

sql/maintenance_utils.sql:40:

CREATE FUNCTION compress_chunk(...) RETURNS REGCLASS AS '@MODULE_PATHNAME@', 'ts_compress_chunk' LANGUAGE C;

第二步:跨模块代理包装器

src/cross_module_fn.c:18-23 的CROSSMODULE_WRAPPER宏:

#define CROSSMODULE_WRAPPER(func) \ TS_FUNCTION_INFO_V1(ts_##func); \ Datum ts_##func(PG_FUNCTION_ARGS) \ { \ PG_RETURN_DATUM(ts_cm_functions->func(fcinfo)); \ } CROSSMODULE_WRAPPER(compress_chunk); // 展开为 ts_compress_chunk()

展开后:

// 自动生成 ts_compress_chunk 函数! Datum ts_compress_chunk(PG_FUNCTION_ARGS) { // 通过函数指针调用真正的实现 PG_RETURN_DATUM(ts_cm_functions->compress_chunk(fcinfo)); }

ts_compress_chunk不是手动写的,是 CROSSMODULE_WRAPPER 宏自动生成的!

第三步:函数指针赋值

CrossModuleFunctions结构体在 cross_module_fn.h:131 有一个字段:

typedef struct CrossModuleFunctions { // ... PGFunction compress_chunk; // 函数指针 PGFunction decompress_chunk; // ... } CrossModuleFunctions;

在 tsl/src/init.c:176 初始化时赋值:

static CrossModuleFunctions tsl_cm_functions = { // ... .compress_chunk = tsl_compress_chunk, // 指向真正的实现! .decompress_chunk = tsl_decompress_chunk, // ... };

ts_module_init()执行时:

ts_cm_functions = &tsl_cm_functions; // 全局函数表指向 TSL 实现

为什么这样设计?双 License 架构

┌──────────────────────────────────────────────────────────┐ │ TimescaleDB 双 License 架构 │ ├──────────────────────────────────────────────────────────┤ │ │ │ src/ 目录 (Apache 2.0 License - 完全开源) │ │ ├── cross_module_fn.c ← CROSSMODULE_WRAPPER 宏 │ │ │ 生成 ts_compress_chunk() 代理函数 │ │ │ 默认函数表 → error_no_default_fn_pg_community │ │ │ (如果只装开源版,调用会报错: "not supported │ │ │ under the current license") │ │ │ │ │ └── cross_module_fn.h ← CrossModuleFunctions 结构体 │ │ │ │ tsl/ 目录 (Timescale License - 商业功能) │ │ ├── init.c ← 赋值函数表 │ │ │ .compress_chunk = tsl_compress_chunk │ │ └── compression/api.c ← 真正的实现 │ │ tsl_compress_chunk() {...} │ │ │ └──────────────────────────────────────────────────────────┘
  • Community 版(只用src/):函数表保留默认值error_no_default_fn_pg_community,压缩功能不可用
  • 完整版(加载tsl/):_PG_init()调用ts_module_init(),将ts_cm_functions指向tsl_cm_functions,所有函数指针替换为真实实现

总结

ts_compress_chunk是真实存在的 C 函数,但它不是手写的 — 它由CROSSMODULE_WRAPPER(compress_chunk)宏自动生成。它就是一张跳板,通过##宏拼接生成:

// 宏: CROSSMODULE_WRAPPER(compress_chunk) // 生成函数名: ts_##compress_chunk → ts_compress_chunk // 函数体: 调用 ts_cm_functions->compress_chunk(fcinfo) // 即 tsl_compress_chunk(fcinfo)

所有以ts_开头、tsl_实现的功能(压缩、解压缩、连续聚合、压缩策略等),都走这套CROSSMODULE_WRAPPERts_cm_functions函数表 → TSL 实现的路径。

http://www.jsqmd.com/news/1096069/

相关文章:

  • PIC32 USB开发板入门:从硬件解析到USB通信实战
  • STM32F1驱动8*8点阵:从硬件连接到自定义字符取模实战
  • Sunshine游戏串流服务器完整指南:3步搭建个人云游戏平台
  • 3个技巧解决Python数据采集中的Cookie验证难题
  • A股代码与公司名称映射全解析:从000001到900957
  • 毕设实战:从Proteus仿真到PCB制板的51单片机数字电压表全流程解析
  • SpringBoot+Vue民宿管理系统:从零到一构建前后端分离的实战指南
  • 投标数字化落地实践:拆解全流程企业级 AI 标书平台的真实价值与适用边界
  • 本地生活门店复购数据诊断模型
  • macOS微信防撤回终极指南:3分钟快速安装完整教程
  • Shiro-550漏洞动态调试与密钥验证实战分析
  • 霍尔信号解码实战:从波形捕获到电机转向与转速的精准测量
  • PrismLauncher-Cracked终极指南:10分钟解锁离线账户限制,畅玩Minecraft
  • 暗黑破坏神2存档编辑器深度解析:从角色数据到游戏自由度的终极掌控
  • ROS2接口定制实战:从零构建msg与srv并集成到C++/Python节点
  • 特斯拉与苹果代工厂被黑,630GB数据被暗网兜售
  • OneMore如何重新定义OneNote工作流:基于XML DOM的智能搜索替换引擎
  • 忽视城市生命线监测可能带来的安全责任风险分析
  • 从黑砖到重生:MTK平台深度刷机实战与SP Flash工具详解
  • 5个技巧掌握LosslessCut无损剪辑,快速处理海量视频素材
  • 一个月挖出数万个 0day、数据极度匮乏、程序员面临冲击:开源下半场的真实战场
  • 终结RCE注入:基于WebAssembly(Wasm)沙箱构建wechatapi的零信任插件执行引擎
  • 稳健性检验:从理论到实践的计量经济学指南
  • 从关键参数到实战选型:一份DDR芯片规格书的精读指南
  • 自动控制原理进阶:从结构图化简到梅逊公式的系统化求解
  • 基于PIC16F1618的单相BLDC电机PID控制与硬件保护实现
  • GoB技术实现:Blender与ZBrush跨平台3D数据交换架构解析
  • 惠州家庭教育推荐哪家
  • 标签打印的革命:LPrint如何用单一可执行文件重塑打印体验
  • CC Switch 配置 Codex 不生效怎么办