编写DuckDB扩展:如何让标量函数返回整数
DuckDB扩展:整数加法函数实现与Executor疑问解答
问题背景
基于DuckDB官方扩展模板,现有一个字符串输入输出的示例函数,想要修改为接收两个整数输入、返回整数结果的加法函数,但不清楚如何操作整数类型的Vector &result,同时对BinaryExecutor的作用和是否能用普通for循环替代存在疑问。
原示例函数:
inline void ExampleScalarFun(DataChunk &args, ExpressionState &state, Vector &result) { auto &name_vector = args.data[0]; UnaryExecutor::Execute<string_t, string_t>( name_vector, result, args.size(), [&](string_t name) { return StringVector::AddString(result, "The provided name is "+name.GetString()+" 🐥"); }); }
当前修改后的(仍返回字符串)版本:
inline void Addition(DataChunk &args, ExpressionState &state, Vector &result) { auto &first_argument_vector = args.data[0]; auto &second_argument_vector = args.data[1]; BinaryExecutor::Execute<int, int, string_t>( first_argument_vector, second_argument_vector, result, args.size(), [&](int a, int b) { return StringVector::AddString(result, "We need to add together " + std::to_string(a) + " and " + std::to_string(b) + " 🐥"); }); }
1. 修改为返回整数的加法函数
要返回整数,需要调整BinaryExecutor的模板参数,并直接处理整数类型的结果Vector:
- 把
BinaryExecutor::Execute的模板参数改为int, int, int(依次是第一个输入类型、第二个输入类型、返回类型) - 核心计算逻辑直接返回整数结果,
BinaryExecutor会自动处理结果写入result
修改后的代码:
inline void Addition(DataChunk &args, ExpressionState &state, Vector &result) { auto &first_arg_vec = args.data[0]; auto &second_arg_vec = args.data[1]; // 模板参数:输入1类型、输入2类型、返回类型 BinaryExecutor::Execute<int, int, int>( first_arg_vec, second_arg_vec, result, args.size(), [&](int a, int b) { // 直接返回加法结果,Executor自动写入result return a + b; }); }
如果需要手动操作Vector(不依赖Executor的自动赋值),可以通过FlatVector工具类直接操作数据指针:
inline void Addition(DataChunk &args, ExpressionState &state, Vector &result) { auto &first_arg_vec = args.data[0]; auto &second_arg_vec = args.data[1]; auto result_data = FlatVector::GetData<int>(result); auto count = args.size(); // 遍历每个元素计算并赋值 for (idx_t i = 0; i < count; i++) { int a = FlatVector::GetValue<int>(first_arg_vec, i); int b = FlatVector::GetValue<int>(second_arg_vec, i); result_data[i] = a + b; } // 标记结果Vector为Flat类型 result.SetVectorType(VectorType::FLAT_VECTOR); }
2. BinaryExecutor的作用
BinaryExecutor是DuckDB为标量函数提供的工具类,核心作用包括:
- 统一处理Vector存储格式:DuckDB的Vector支持Flat、Constant、Dictionary等多种存储类型,Executor会自动适配这些格式,无需手动判断
- 自动处理空值:内置空值检查逻辑,跳过或按规则处理空值元素,避免手动编写空值判断代码
- 底层性能优化:内部做了循环展开、类型对齐等优化,比手写普通for循环效率更高
- 简化代码逻辑:只需要关注核心计算逻辑,无需手动处理数据指针、索引遍历等冗余操作
3. 能不能用for循环替代?
可以用普通for循环替代,但需要注意以下问题:
- 必须手动适配Vector的不同存储类型(比如ConstantVector只需要取一次常量值,不需要遍历所有元素)
- 必须手动检查和处理空值,否则会出现计算错误
- 手写循环的性能通常不如
BinaryExecutor,因为Executor做了底层优化 - 代码量会增加,需要更多的边界处理和模板适配逻辑
如果是测试场景,手写循环可以满足需求,但生产级扩展推荐使用BinaryExecutor,减少冗余代码和潜在bug。
内容的提问来源于stack exchange,提问作者Eerik Sven Puudist
相关产品推荐
相关产品推荐

