You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

编写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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 14:28:26