尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

OceanBase 插件体系全解析:从 legacy `obp_*` 导出符号到 v2 纯 C vtable 契约框架

OceanBase 插件体系全解析:从 legacy `obp_*` 导出符号到 v2 纯 C vtable 契约框架 OceanBase 插件体系全解析从 legacyobp_*导出符号到 v2 纯 C vtable 契约框架【免费下载链接】oceanbaseOceanBase is the unified distributed database for the AI era — open-source, multi-model, one engine for your most demanding workloads.项目地址: https://gitcode.com/GitHub_Trending/oc/oceanbase导读本文围绕 src/plugin/README.md 及其两份子 README完整解析 OceanBaseOB当前开源的两套插件体系最早期的通用插件框架legacy/与新一代插件框架v2/。你将掌握两套体系的目录结构、插件契约与加载机制、二者在宿主能力注入方式、插件类型扩展、ABI 演进上的本质差异以及驱动外表插件做表扫描的执行器 row iter 在 SQL 执行层中的位置。适合需要为 OB 编写外部数据源插件如外表格式插件或阅读 OB 插件相关源码的开发者。一、总览OB 的两套插件体系OB 的插件能力集中在src/plugin/目录下分为legacy/与v2/两个子目录各自维护独立的 READMElegacy/README.md、v2/README.md。两套体系的核心定位如下目录说明legacy/最早的通用插件框架兼容维护中插件只依赖include/oceanbase/SDK回调 OB 靠obp_*导出符号v2/新一代插件框架纯 C vtable 契约宿主能力经回调表注入无导出符号外表格式插件是首个插件类型一个容易踩坑的关键注记主 README 特别强调驱动外表插件做表扫描的执行器 row iter 属于 SQL 执行层统一放在src/sql/engine/table/下与其他格式 row iter 并列不在src/plugin/目录内。对应两个文件ob_ext_table_plugin_row_iter.*—— v2 外表契约的执行器见 ob_ext_table_plugin_row_iter.hob_ext_table_java_plugin_row_iter.*—— legacy 内建插件JNI 数据源的执行器。从源码看v2 的ObExtTablePluginRowIterator继承自ObExternalTableRowIterator在init()时若对应格式的插件.so未加载会直接返回OB_NOT_SUPPORTED运行时通过plan_create / reader_create / reader_open_scan / reader_open_task / reader_next_batch / reader_close_*驱动插件 vtable并用ObArrowDataLoader将每个 Arrow batch 导入 OB 输出向量。也就是说插件只负责产出数据批真正把数据搬进 OB 执行引擎的 row iter 是 SQL 层代码。二、legacy/ —— 兼容维护中的通用插件框架legacy/是 OB 最早的插件体系插件以.so形式独立编译只依赖include/oceanbase/下的 SDK 头文件运行时由 observer 通过dlopen加载。插件对obp_*符号的未定义引用由 observer 主程序通过链接选项-Wl,--export-dynamic-symbolobp_*导出的动态符号表来解析。该链接选项可以在 src/observer/CMakeLists.txt 中直接看到第 774 行附近legacy/export/下的obp_*实现也依赖这个机制保留、不被链接器裁剪。目录结构目录作用include/oceanbase/对外公开的 C 插件 SDK外部插件只应依赖这里的头文件interface/各类插件的内部接口描述ftparser / kms / 外部表等插件类型的内部调用模型sys/插件管理内置插件初始化、动态库加载dl handle / entry handle、插件查找adaptor/适配器把对外的 C 插件接口适配到 OB 内部接口plugin / ftparser / kmsexport/插件 API 的 OB 侧实现obp_*符号allocator / charset / log / ftparser / kms。内部不使用靠 export-dynamic-symbol 保留share/共享工具ObProperties等external_table/内建外部表插件java / odps 等 JNI 数据源OB 管 schema插件描述与声明宏OBP_DECLARE_PLUGINlegacy插件的身份证是 ob_plugin.h 中定义的ObPlugin结构与OBP_DECLARE_PLUGIN宏OBP_DECLARE_PLUGIN(example_plugin) { OceanBase Corporation, // author OBP_MAKE_VERSION(1, 0, 0), // version OBP_LICENSE_APACHE_V2, // license plugin_init, // init routine plugin_deinit, // deinit routine (optional) } OBP_DECLARE_PLUGIN_END;要点插件类型枚举ObPluginType定义了OBP_PLUGIN_TYPE_FT_PARSER全文检索 parser 插件、OBP_PLUGIN_TYPE_EXTERNAL外部表数据资源、OBP_PLUGIN_TYPE_KMSKMS 插件。版本宏OBP_PLUGIN_API_VERSION_CURRENT目前为0.3.0OBP_MAKE_VERSION(major, minor, patch)将三个字段编码为uint64_t版本号。动态/静态两种形态OBP_DYNAMIC_PLUGIN定义下会导出OBP_DYNAMIC_PLUGIN_NAME_VAR、OBP_DYNAMIC_PLUGIN_API_VERSION_VAR等符号否则作为静态插件直接编进 observer。许可字符串提供OBP_LICENSE_GPL / BSD / MIT / APACHE_V2等常量也允许自定义字符串。参数交互ObPluginParamPtr即ObPluginDatum配合obp_param_plugin()、obp_param_plugin_user_data()、obp_param_set_plugin_user_data()使用插件可在 init/deinit 中读写插件实例特定数据。sys/目录负责插件的装载与生命周期管理ob_plugin_builtin.*内置插件初始化、ob_plugin_dl_handle.*/ob_plugin_entry_handle.*动态库句柄与入口句柄、ob_plugin_mgr.*插件查找与管理、ob_plugin_load_param.*加载参数。adaptor/下的ob_plugin_ftparser_adaptor.*、ob_plugin_kms_adaptor.*则把 C 插件接口适配到 OB 内部调用模型ob_plugin_kms_client.*是 KMS 的客户端封装。三、v2/ —— 新一代插件框架纯 C vtable 契约v2/是 legacy 的继替者核心设计是纯 C vtable 契约每种插件一个独立.soOB 通过dlopen dlsym解析单入口符号拿到整张 vtable宿主能力内存 / IO / 执行器 / 日志以回调表host API在运行时注入插件不向插件导出任何 OB 符号—— 这正是与 legacyobp_*导出符号机制的本质区别。目录结构目录作用include/插件契约头插件唯一需要包含的头host/宿主能力的 OB 侧实现loader/通用 dlopen 加载器external_table/外表插件类型的 OB 侧消费方1. 契约头include/—— 插件唯一需要包含的东西ob_external_table_plugin.h插件要实现的 vtable ABI 版本 入口符号ob_ext_host_api.hOB 提供给插件的宿主 APImem / executor / io / log 回调表ob_external_table_protocol.h控制面协议词汇表契约 errno JSON key。注意一个工程约定这些头与ob-deps/patch/paimon/ob_plugin/下的同名文件内容必须保持一致以本仓库为源。2. 数据面与控制面分离Arrow C Data JSON 控制面ob_external_table_plugin.h的开头注释完整定义了 v2 外表契约的两个平面数据面 Arrow C Data行批通过reader_next_batch以ArrowArray/ArrowSchema形式流动——二进制、零拷贝、高吞吐绝不使用 JSON控制面 JSON 文本schema、谓词、统计信息和扫描任务描述符都以 UTF-8 JSON 字符串const char* length传递。ABI 表面因此极小vtable 函数签名 char*缓冲区 host API 不透明 reader 状态引用。演进一个控制结构新增列属性、谓词操作符、统计项、扫描任务字段只是 JSON schema 变更不是 ABI 破坏——旧插件忽略未知 key新 OB 容忍缺失的可选 key仅有文档标注为 required 的字段保持强制。这就是独立编译、独立发布的.so能跨版本共存的根本原因。JSON 值编码规则避免精度丢失在契约头中有明确表格OB 类型JSON 编码boolJSON boolint int32JSON numberint64 / bigintJSON string避开 2^53 的 double 上限float / doubleJSON numberdecimalJSON string如1.23dateJSON number距 epoch 的天数datetime / timestamp / timeJSON string如2024-01-01 00:00:00binary / varbinaryJSON stringbase64string / varchar / charJSON stringnull / unknownJSON null3. 协议类型词汇表ob_ext_obj_typev2 契约定义了协议化类型枚举ob_ext_obj_typeob_external_table_plugin.h列类型由插件决定OB 负责映射到ObObjType。枚举值保持稳定因为 OB 的ob_ext_obj_type - ObObjTypemapper 依赖它们它保留了 Arrow 会丢失的区分varchar vs string vs char、decimal 精度/刻度、datetime vs timestamp、嵌套 array/map。控制面 JSON 中类型以枚举的名字字符串如BIGINT出现OB 侧通过ext_type_from_name解析。4. 内存所有权严格约定契约的内存所有权规则非常严格插件输出schema / scan-tasks / stats JSON由插件释放OB 从不释放。因为缓冲区可能来自静态常量、host-mem.mem_alloc或插件自有分配器只有插件知道怎么释放。因此每个输出都有配对的 destroy 回调schema_destroy/tasks_destroy/stats_destroyOB 拷贝/解析完缓冲区后调用插件内部决定是 no-op静态还是host-mem.mem_freehost 分配。host参数会传给每个 destroy保证用 host 分配器的插件仍能触达host-mem.mem_free。OB 输入给插件options / predicate / projection JSON由 OB 拥有只在调用期间有效插件必须解析成自己的原生形态绝不能保留指针超过调用期。跨边界唯一的非 JSON 句柄是不透明、插件所有的 reader 状态引用通过reader_close一起释放。host-mem.mem_alloc / mem_free供插件自己的内部缓冲区使用如 arrow 内存池不是OB 释放插件输出的方式。5. 控制面 JSON 协议契约头给出了完整协议示例。optionsOB→插件{location:..,access_info:.., ext_options:{format-private knobs}}ext_options是不透明嵌套对象OB 原样透传OB 不认识其中任何内部 key由插件自行解包与校验缺省即默认。表 schema插件→OBext_type使用枚举名字{columns:[{name:..,field_id:N,ext_type:BIGINT, precision:P,scale:S,length:L,nullable:true}]}ARRAY 列携带单个 child递归、同构{columns:[{name:tags,field_id:N,ext_type:ARRAY,nullable:true, children:[{name:element,field_id:M,ext_type:STRING, nullable:true}]}]}ARRAY of ARRAY 就是 child 的 ext_type 也是 ARRAY。MAP 列携带 key/value 两个 child{columns:[{name:attrs,field_id:N,ext_type:MAP,nullable:true, children:[{name:key,field_id:M,ext_type:STRING, nullable:false}, {name:value,field_id:K,ext_type:INT, nullable:true}]}]}分区列作为顶层名字列表携带partition_keys形如[ds,hr]。谓词 / 分区过滤OB→插件是表达式树{kind:cmp,op:eq, children:[{kind:col,col_idx:N,name:..}, {kind:lit,value:..}]}kindslit / col / cmp / in / not_in / is_null / is_not_null / and / or / notcol的col_idx是列的 field_id信息性name由插件解析到自己的 schema 字段索引/类型lit的 value 是字符串形式的字面量插件按兄弟 col按名字解析的字段类型转换cmp是二元节点children[col, lit]op 属于eq/ne/lt/le/gt/gein/not_in的 children[col, lit, lit, ...]is_null/is_not_null的 children[col]and/or的 children[pred, ...]not的 children[pred]根节点为 NULL 或表示不下推。scan tasks插件→OB携带插件所有的 split 与可选的plan-atomic OB 文件读取器指令{partition_filter_applied:true, tasks:[{row_count:N,byte_size:N, partition_values:[{field_id:N,value:2025-01-15}, {field_id:M,value:null}], ob_file_scan:{version:1,file_format:parquet, files:[{path:..,byte_size:N, row_count:N}]}, plugin_split:..}]}partition_values每个 task 都要产出。分区表要求每个分区 key 恰好一个按 schema 顺序的条目task 代表的每个文件必须属于该元组缺失或非法元数据是硬性计划错误。JSON null 表示配置的默认分区。非分区表缺失或[]表示无分区非空元组则非法。ob_file_scan是plan-atomic的缺省时整批数据留在插件 reader 上合法描述符则选择 OB 文件读取器执行期间不会回退到plugin_split。版本 1 支持 parquet/orc要求非空 files 数组每个条目 path 非空、size 非负、row_count 精确非负。出现非法描述符、混合出现、混合格式都是硬性计划错误。statistics插件→OB{table:{row_count:N,byte_size:N}, columns:[{col_idx:N,row_count:N,null_count:N,ndv:N, min:..,max:..}]}6. 错误模型直接返回 OB errno每个返回错误的函数直接返回 OB errno0 OB_EXT_SUCCESS负数 错误使用契约头中定义的OB_EXT_*枚举插件编译时不需要 OB 的ob_errno.h。出错时插件必须先用host-log(...)插件侧的OBEXT_LOG_*宏会捕获__FILE__/__LINE__/__func__让 observer.log 里能看到插件侧的源码位置记录诊断再返回 errno。跨边界没有错误对象——没有ObExtError没有error_message/error_destroy槽位OB 只消费 int 返回值消息活在日志行里。成功调用返回OB_EXT_SUCCESS且不记日志。errno 值是 OB errno 原样如OB_EXT_NOT_SUPPORTED OB_NOT_SUPPORTED -4007OB 直接把返回值赋给ret无翻译层。协议词汇表在 ob_external_table_protocol.h 中定义包含两类词汇契约 errnoOB_EXT_*允许跨界面的唯一错误值。值就是 OB errno 原样OB_EXT_SUCCESS0、OB_EXT_INVALID_ARGUMENT-4002、OB_EXT_NOT_SUPPORTED-4007、OB_EXT_IO_ERROR-4009、OB_EXT_ALLOCATE_MEMORY_FAILED-4013、OB_EXT_ERR_UNEXPECTED-4016、OB_EXT_ENTRY_NOT_EXIST-4018、OB_EXT_FILE_NOT_EXIST-4027、OB_EXT_DESERIALIZE_ERROR-4034、OB_EXT_DIR_NOT_EXIST-4066、OB_EXT_INVALID_DATA-4070、OB_EXT_OLD_SCHEMA_VERSION-4177。OB 在 ob_ext_plugin_loader.cpp 中通过 static_assert 编译期校验相等性。JSON 字段名OB_EXT_K_*控制面文档的 key。OB 与每个插件必须引用这些常量而不是裸字符串字面量这样 typo 或改名在单一定义处就是编译错误而不是静默的运行时错配。未知 key 不会被静默忽略——OB 会打一条响亮的 WARNrequired key 缺失或类型不匹配是硬错误。7. 可选槽位优雅降级契约头明确列出了哪些槽位可以为 NULL以及对应的降级行为槽位为 NULL降级行为init/deinit不做进程级初始化fetch_statistics无统计OB 用默认基数schema_destroy/tasks_destroy/stats_destroy仅当插件保证对应输出永远是静态常量无需 free时安全OB 的 helper 会做空指针检查。插件只要曾经分配过输出缓冲区就必须实现对应 destroy否则泄漏predicate/partition_filter/read_projection不下推 / 读全部列recognize_tableOB 对该格式使用内建 fallback 规则只实现{load_schema, plan_create, reader_create, reader_open_scan, reader_open_task, reader_next_batch, reader_close_task, reader_close_scan, reader_close}的插件就是完整可用的。8. vtable 全貌与三段式 reader 状态vtable 结构ObExtTablePluginApi见 ob_external_table_plugin.h由以下部分组成身份plugin_name()、plugin_version()、format_name()OB 动态注册到格式表的规范格式字符串、可选的init/deinit格式识别recognize_table(table_uri, recognize_json, host)—— 判断本插件是否拥有该表返回OB_SUCCESS即是我的其他 errno 即不是我的schema按表缓存load_schema产出 schema JSONschema_destroy释放计划/扫描任务plan_create消费 partition_filter / predicate返回全部 scan tasks 的 JSONtasks_destroy释放。limit -1表示不限制desired_task_count是 PX 并行度提示可忽略。catalog/plan schema 漂移时可返回OB_OLD_SCHEMA_VERSIONreader每个 row iterator 三个持久状态对象workerreader_create/reader_close持有迭代器 init 时已知的读配置table_uri / options / projectionscanreader_open_scan/reader_close_scan持有由 worker 常量 本次 scan 谓词构建的读管道taskreader_open_task/reader_next_batch/reader_close_task持有 split batch reader。外层状态是内层 open 调用的只读输入open_scan 只能改 scanopen_task 只能改 task。reader_next_batch返回 0 有 batch调用者拥有并须释放 arr/sch、1 EOF、0 OB errno。reader_open_task的start_row/row_count是行区间细分传 0 / task_row_count 表示整个 task。统计可选fetch_statistics(table_uri, options_json, partition_filter_json, ...)stats_destroy释放。入口符号是唯一的const struct ObExtTablePluginApi* ob_ext_table_plugin_get_api(unsigned int abi_version);当前OB_EXT_TABLE_PLUGIN_ABI_VERSION 2。OB 通过 dlsym 解析这个符号ABI 版本不匹配时插件返回 NULL。.so缺失dlsym 失败时 OB 报告错误——一个格式只有在它的.so存在时才可选。9. host API注入的宿主能力ob_ext_host_api.h 定义ObExtTableHostApi把 OB 能力按三张函数表 日志回调暴露给插件。所有回调都收到顶层host-ctxmemObExtMemApimem_alloc(ctx, size, alignment)/mem_free/mem_realloc/mem_bytes_allocated。这是唯一允许跨边界的分配器。alignment非零时宿主必须遵守如 arrow 的 64 字节对齐mem_alloc(0)必须返回非 NULL 占位符mem_free的size仅作信息用途实现必须按指针释放、不得依赖 size。executorObExtExecutorApiexec_submit(ctx, fn, arg)、exec_thread_count(ctx)。exec_submit返回 0 表示任务被接受宿主保证被接受的任务会运行——即使关闭期间也会 drain因为插件只在任务运行时回收 per-task 资源非零表示宿主拒绝且未接管所有权插件需自行回收资源可回退为内联执行。ioObExtIoApi只读文件系统 目录列举。file_open / file_read / file_read_at / file_tell / file_seek / file_length / file_close / file_exists / file_status / list_dir。约定file_read/file_read_at返回字节数00 EOF-1 错误file_seek返回 0/-1origin 是OB_EXT_SEEK_SET/CUR/ENDfile_open返回流句柄或 NULLfile_exists返回 1/0/-1list_dir非递归遍历子项is_dir为 1 表示目录。log把已格式化好的插件消息路由进 OB 的 loggerfile/line/func传插件侧调用点__FILE__/__LINE__/__func__新插件应该用它替代 stdout/stderr让诊断落进 observer.log。日志级别OB_EXT_LOG_TRACE/INFO/WARN/ERROR由宿主映射到 OB 日志级别。OB 侧的 host 实现位于v2/host/ob_ext_mem_pool.*内存池、ob_ext_file_system.*只读文件系统、ob_ext_malloc_guard.hmalloc 标签守卫、ob_ext_host_provider.*HostApi 组装把通用能力装成契约的ObExtTableHostApi。四、v2 loader懒加载、SONAME 约定与常驻句柄ob_ext_plugin_loader.h 描述通用 dlopen 加载器懒加载从集群参数ext_plugin_config懒加载——第一次注册表查找ObExtFormatRegistry::get_plugin_by_slot/recognize_format时读取配置并 dlopen 所有命名的插件。未加载的格式只是不在注册表中访问其表会报plugin not loaded。定位.so的两种方式显式绝对路径配置项的path字段SONAME 约定lib_ob_name.so小写在LD_LIBRARY_PATH下搜索。搜索前先把_ob_additional_lib_path支持:分隔的多目录ensure 进LD_LIBRARY_PATH再搜索统一环境——与 libhdfs.so / libjvm.so 走同一路径ObLdLibraryPathUtil。常驻通过版本检查的句柄进程生命周期内常驻从不 dlclose函数指针与插件初始化的全局状态都在使用中。加载失败dlopen / dlsym / ABI 不匹配 / 找不到则不留任何常驻物损坏句柄由load_ext_plugindlclose 掉版本检查通过前其符号未被使用安全运维人员修复/替换.so后下次重启生效。加载结果分类ObExtPluginLoadStatus枚举细分了失败原因EXT_PLUGIN_NOT_FOUND、DLOPEN_FAILED、NO_SYMBOL、ABI_MISMATCH、NO_FORMAT_NAME、ALREADY_LOADED等供注册表打诊断日志。五、注册表与配置ext_plugin_config 与稳定槽位ob_ext_format_registry.h 是进程级的外表格式插件注册表几个关键设计声明式配置ext_plugin_config集群参数是一个 JSON 数组元素为{name:...,path:...}对象是进程加载哪些插件的唯一声明性来源。没有LOAD PLUGIN命令、没有启动扫描、没有 per-attempt 状态表。配置每个进程最多读一次之后ALTER SYSTEM SET ext_plugin_config只改持久化值下次重启生效已常驻的集合不受影响。单插件失败不影响整体单个插件加载失败dlopen/dlsym/ABI 不匹配/找不到只记日志并跳过不中止其余条目、不使查找失败——缺失插件只是返回not loaded。内存模型加载路径在std::call_once下每进程恰好执行一次读路径无锁call_once 的 synchronizes-with 把唯一写阶段与所有读阶段隔开读方看到一致的plugins_[]快照api_nullptr的洞就是加载失败的配置条目。稳定槽位STABLE SLOT插件身份在运行时流程plan struct / CG / iter / DAS中携带的是 int16 稳定槽位[0, MAX_PLUGINS)不是格式名字符串。槽位 插件在plugins_[]中的数组下标在加载时按ext_plugin_config的 JSON 数组顺序分配——它不是运行时计数器因此只要配置相同所有服务器的同一插件槽位一致与每个条目的加载成败无关。失败的配置条目留下一个洞plugins_[i]保持api_nullptr后续条目仍用自己的下标、不会前移。格式名只活在注册表内部配置解析 recognize_format的逐插件探测。可观测性ObExtPluginStatus结构对应__all_virtual_plugin_info虚拟表的一行——某个配置声明插件的加载结果成功或失败的只读快照包含plugin_name_、lib_path_实际 dlopen 的绝对路径或失败时尝试的 soname/路径、plugin_version_、error_msg_、status_、load_time_us_通过get_plugin_statuses()拷贝出去。native 格式如 ICEBERG、HIVE继续走各自的专用代码路径不碰槽位轴。六、v2 外表插件的 OB 侧消费方v2/external_table/是外表插件类型的 OB 侧消费方文件职责ob_ext_format_registry.*插件注册与槽位管理上文所述ob_ext_json_protocol.*ob_ext_json_internal.h控制面 JSON 编解码ob_ext_schema_parser.*schema JSON 解析ob_ext_type_mapper.*协议类型 → OB 类型映射ob_ext_obj_type→ObObjTypeob_ext_table_metadata.*表元数据ob_ext_plugin_util.*契约 destroy 包装scan tasks 由优化器侧的插件 pruner 产出通过现有 PX 路径分发执行时迭代器把实例化的存储过滤转成可选的 predicate JSON 传给reader_open_scan。CPP_PLUGIN 不会把树复制进spec.filters_因此该迭代器总是通过calc_filters计算pd_storage_filters_作为正确性兜底见 ob_ext_table_plugin_row_iter.h。七、两套体系的角色对应关系角色legacyv2插件可见头文件legacy/includev2/includeOB 提供给插件的服务legacy/exportobp_*符号导出v2/host回调表注入插件加载/管理legacy/sysv2/loader插件类型的 OB 侧消费方legacy/adaptor legacy/external_tablev2/external_table新插件类型一律进v2/纯 C vtable 回调表注入无导出符号legacy 仅兼容维护不再扩展。八、小结与源码导航两套插件体系的本质差异可以用一句话概括legacy 用导出符号把 OB 能力交给插件v2 用回调表注入把 OB 能力送进插件——前者要求 observer 通过-Wl,--export-dynamic-symbolobp_*暴露符号见 src/observer/CMakeLists.txt后者通过ObExtTableHostApi在运行时注入 mem / executor / io / log 四类回调见 ob_ext_host_api.h。v2 的 JSON 控制面让新增列属性、谓词算子、统计项都变成 JSON schema 演进而非 ABI 变更从而支撑独立编译、独立发布的插件.so跨版本共存。继续深入时推荐按以下路径阅读src/plugin/README.md —— 两套体系总览src/plugin/legacy/README.md 与 src/plugin/v2/README.md —— 各目录职责ob_external_table_plugin.h —— vtable、ABI 版本、内存所有权、JSON 协议本文主体依据ob_external_table_protocol.h —— 契约 errno 与 JSON key 单一来源ob_ext_host_api.h —— 宿主回调表ob_ext_plugin_loader.h 与 ob_ext_format_registry.h —— 懒加载与稳定槽位机制ob_ext_table_plugin_row_iter.h —— SQL 执行层如何驱动插件 vtable 并导入 Arrow batch。【免费下载链接】oceanbaseOceanBase is the unified distributed database for the AI era — open-source, multi-model, one engine for your most demanding workloads.项目地址: https://gitcode.com/GitHub_Trending/oc/oceanbase创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表