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

如何用TFDSQLiteFunction实现正确的自定义聚合函数(如SQRT_SUM)?

自定义SQLite聚合函数(FireDAC)实现指南:以SQRT_SUM为例

需求场景

需要在FireDAC中实现自定义SQLite聚合函数(示例为SQRT_SUM,实际需求为标准差这类统计函数),用于如下SQL查询:

FDQuery1->SQL->Text = "SELECT SQRT_SUM(FIELD_1) FROM TABLE_1 WHERE ID = 1";
FDQuery1->Open();

ShowMessage(Form1->FDQuery1->Fields->Fields[0]->AsFloat);

FDQuery1->Close();

遇到的问题

参考官方教程实现的代码会被逐行调用,若不使用全局变量则无法正确累加所有行的数值,得不到预期的聚合结果。

解决方案:利用AUserData存储中间状态

SQLite聚合函数的执行分为初始化、逐行累加、最终计算三个阶段,FireDAC通过AUserData指针提供线程安全的中间状态存储,无需依赖全局变量。

正确的代码实现

void __fastcall TForm1::FDSQLiteFunction1Calculate(TSQLiteFunctionInstance *AFunc,
          TSQLiteInputs *AInputs, TSQLiteOutput *AOutput, TObject *&AUserData)
{
    // 初始化或最终计算阶段(无输入参数)
    if (AInputs->Count == 0) {
        if (AUserData == nullptr) {
            // 初始化:分配内存存储累加值
            AUserData = new double(0.0);
        } else {
            // 最终计算:取出累加值,计算平方根并输出
            double sum = *static_cast<double*>(AUserData);
            AOutput->AsFloat = sqrt(sum);
            // 释放内存,避免泄漏
            delete static_cast<double*>(AUserData);
            AUserData = nullptr;
        }
        return;
    }

    // 逐行累加阶段(有输入参数)
    if (AInputs->Inputs[0]->IsValid) {
        double currentValue = AInputs->Inputs[0]->AsFloat;
        // 将当前值累加到中间存储的总和中
        *static_cast<double*>(AUserData) += currentValue;
    }
}

// 函数注册代码
FDSQLiteFunction1->DriverLink = FDPhysSQLiteDriverLink1;
FDSQLiteFunction1->FunctionName = L"SQRT_SUM";
FDSQLiteFunction1->Aggregated = true;
FDSQLiteFunction1->ArgumentsCount = 1;
FDSQLiteFunction1->OnCalculate = FDSQLiteFunction1Calculate;
FDSQLiteFunction1->Active = true;

代码关键点说明

  • 初始化阶段:当AInputs->Count == 0且AUserData为空时,分配内存存储累加的初始值(0.0)。
  • 逐行累加阶段:每次传入当前行的FIELD_1值,将其累加到AUserData指向的变量中。
  • 最终计算阶段:当AInputs->Count == 0且AUserData不为空时,取出累加总和计算平方根,输出结果后释放内存。
  • 线程安全:AUserData为每个查询实例独立分配,避免全局变量的线程冲突问题。

内容的提问来源于stack exchange,提问作者Bruce

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 11:26:18