Apache Doris 原生C++ UDF之Coding(2)1

简介: Apache Doris 原生C++ UDF之Coding(2)1

Apache Doris 原生C++ UDF之Coding(2)

一、环境信息

1.1 硬件信息

1.2 软件信息

二、自定义TIME_TO_SEC函数

2.1 源码开发 & 实现一

2.1.1 测试主函数

2.1.2 UDF头文件

2.1.3 UDF源文件

2.1.4 实现方式一小结

2.2 源码开发 & 实现二

2.2.1 测试主函数

2.2.2 UDF头文件

2.2.3 UDF源文件

2.2.4 实现方式二小结

三、编译结果

四、函数使用

4.1 创建 UDF 函数

4.2 使用UDF 函数

五、总结

一、环境信息

1.1 硬件信息

  1. 1.CPU :4C
  2. 2.CPU型号:x64(AVX2)
  3. 3.内存 :10GB
  4. 4.硬盘 :66GB SSD

1.2 软件信息

  1. 1.Linux版本 :CentOS-7
  2. 2.Apahce Doris版本 :0.15-release
  3. 3.CodeBlocks版本:20.03mingw

二、自定义TIME_TO_SEC函数

实现传入一个时间参数,将其时间部分转换成秒的UDF。

2.1 源码开发 & 实现一

2.1.1 测试主函数

//time_to_sec 的语法格式
//  TIME_TO_SEC(time)
//语法格式说明
//time:传入时间,如果传入了日期部分,也不会管,只将时间部分转换成秒
//重点:是指将传入的时间转换成距离当天00:00:00的秒数,00:00:00为基数,等于 0 秒
#include <iostream>
#include <string>
#include <regex>
using namespace std;
int time_to_sec(string text)
{
    // clear other str
    regex r("^((?![0-9]{2}:[0-9]{2}:[0-9]{2}).)*");
    string time = regex_replace(text, r, "");
    cout << time << endl;
    // handle abnormal
    if(time.length() != 8)
        return NULL;
    // get hh mm ss
    int HH = atoi(time.substr(0,2).c_str());
    int MM = atoi(time.substr(3,2).c_str());
    int SS = atoi(time.substr(6,2).c_str());
    // return sum sec
    return HH*3600 + MM*60 + SS;
}
int main()
{
    cout<<time_to_sec("1987-01-01 00:39:38")<<endl;
    return 0;
}

2.1.2 UDF头文件

C++
#pragma once
#include "udf.h"
#include <bits/stdc++.h>
namespace doris_udf {
IntVal TIME_TO_SEC(FunctionContext* context, const StringVal& time);
/// --- Prepare / Close Functions ---
/// ---------------------------------
/// The UDF can optionally include a prepare function. The prepare function is called
/// before any calls to the UDF to evaluate values.
void AddUdfPrepare(FunctionContext* context, FunctionContext::FunctionStateScope scope);
/// The UDF can also optionally include a close function. The close function is called
/// after all calls to the UDF have completed.
void AddUdfClose(FunctionContext* context, FunctionContext::FunctionStateScope scope);
}

2.1.3 UDF源文件

C++
#include "time_to_sec.h"
namespace doris_udf {
IntVal TIME_TO_SEC(FunctionContext* context, const StringVal& time) {
    // handle null
    if (time.is_null) {
        return IntVal::null();
    }
    // clear other str
    using namespace std;
    const string timestr((char *)time.ptr);
    const regex r("^((?![0-9]{2}:[0-9]{2}:[0-9]{2}).)*");
    const string replace_str = "";
    string hms_time = regex_replace(timestr, r, replace_str);
    // handle str abnormal
    if(hms_time.length() != 8) {
        return IntVal::null();
    }
    // get hh mm ss
    int HH = atoi(hms_time.substr(0,2).c_str());
    int MM = atoi(hms_time.substr(3,2).c_str());
    int SS = atoi(hms_time.substr(6,2).c_str());
    // return sum sec
    return HH*3600 + MM*60 + SS;
}
/// --- Prepare / Close Functions ---
/// ---------------------------------
void AddUdfPrepare(FunctionContext* context, FunctionContext::FunctionStateScope scope) {}
void AddUdfClose(FunctionContext* context, FunctionContext::FunctionStateScope scope) {}
}

2.1.4 实现方式一小结

不建议使用,doris对其中的regex相关函数并不友好,会直接导致be所有节点crash。

2.2 源码开发 & 实现二

2.2.1 测试主函数

C++
//time_to_sec 的语法格式
//  TIME_TO_SEC(time)
//语法格式说明
//time:传入时间,如果传入了日期部分,也不会管,只将时间部分转换成秒
//重点:是指将传入的时间转换成距离当天00:00:00的秒数,00:00:00为基数,等于 0 秒
#include <iostream>
#include <string>
#include <regex>
using namespace std;
int time_to_sec(string text)
{
   // clear other str
   string segSign = ":";
   string::size_type pos1 = text.find(segSign);
   if(pos1 == string::npos)
      cout << "没找到!" << endl;
   else
      cout << "找到了!下标:" << pos1<<endl;
    string time = text.substr(pos1-2,8);
    cout << time << endl;
    // handle abnormal
    if(time.length() != 8)
       return NULL;
    // get hh mm ss
    int HH = atoi(time.substr(0,2).c_str());
    int MM = atoi(time.substr(3,2).c_str());
    int SS = atoi(time.substr(6,2).c_str());
    // return sum sec
    return HH*3600 + MM*60 + SS;
}
int main()
{
    cout<<time_to_sec("1987-01-01 00:39:38")<<endl;
    return 0;
}

2.2.2 UDF头文件

C++
#pragma once
#include "udf.h"
#include <bits/stdc++.h>
namespace doris_udf {
IntVal TIME_TO_SEC(FunctionContext* context, const StringVal& time);
/// --- Prepare / Close Functions ---
/// ---------------------------------
/// The UDF can optionally include a prepare function. The prepare function is called
/// before any calls to the UDF to evaluate values.
void AddUdfPrepare(FunctionContext* context, FunctionContext::FunctionStateScope scope);
/// The UDF can also optionally include a close function. The close function is called
/// after all calls to the UDF have completed.
void AddUdfClose(FunctionContext* context, FunctionContext::FunctionStateScope scope);
}

2.2.3 UDF源文件

C++
#include "time_to_sec.h"
namespace doris_udf {
IntVal TIME_TO_SEC(FunctionContext* context, const StringVal& time) {
    // handle null
    if (time.is_null) {
        return IntVal::null();
    }
    // clear other str
    using namespace std;
    string timestr((char *)time.ptr);
    string segSign = ":";
    string::size_type pos = timestr.find(segSign);
    string hms_time;
    if(pos == string::npos)
        return IntVal::null();
     else
        hms_time = timestr.substr(pos-2,8);
    // handle str abnormal
    if(hms_time.length() != 8) {
        return IntVal::null();
    }
    // get hh mm ss
    int HH = atoi(hms_time.substr(0,2).c_str());
    int MM = atoi(hms_time.substr(3,2).c_str());
    int SS = atoi(hms_time.substr(6,2).c_str());
    // return sum sec
    IntVal result;
    result.val = HH*3600 + MM*60 + SS;
    return {result.val};
}
/// --- Prepare / Close Functions ---
/// ---------------------------------
void AddUdfPrepare(FunctionContext* context, FunctionContext::FunctionStateScope scope) {}
void AddUdfClose(FunctionContext* context, FunctionContext::FunctionStateScope scope) {}
}

2.2.4 实现方式二小结

基本完全使用字符串的API实现,简单高效并且兼容性较好,最终选定实现二。

目录
打赏
0
0
0
0
3
分享
相关文章
6/14 上海,Apache Doris x 阿里云 SelectDB AI 主题线下 Meetup 正式开启报名!
6 月 14 日,由 Apache Doris 社区、飞轮科技、阿里云联合发起的湖仓数智融合、AI 洞见未来:Apache Doris x 阿里云 SelectDB 联合 Meetup 将在上海·汇付天下总部大楼正式开启,邀您一同探索 AI 与数据分析的融合实践!
252 76
【倒计时3天】NineData x Apache Doris x 阿里云联合举办数据库技术Meetup,5月24日深圳见!
5月24日,NineData联合Apache Doris与阿里云在深圳举办数据库技术Meetup。活动聚焦「数据实时分析」与「数据同步迁移」两大领域,邀请行业专家分享技术趋势、产品实践及解决方案,助力企业构建高效安全的数据管理体系。时间:14:00-17:30;地点:深圳新一代产业园2栋20楼会议室。线下名额有限(80人),速报名参与深度交流!
70 1
网易游戏 x Apache Doris:湖仓一体架构演进之路
网易游戏 Apache Doris 集群超 20 个 ,总节点数百个,已对接内部 200+ 项目,日均查询量超过 1500 万,总存储数据量 PB 级别。
网易游戏 x Apache Doris:湖仓一体架构演进之路
Apache Doris 2025 Roadmap:构建 GenAI 时代实时高效统一的数据底座
秉承“以场景驱动创新” 的核心理念,持续深耕三大核心场景的关键能力,并对大模型 GenAI 场景的融合应用进行重点投入,为智能时代构建实时、高效、统一的数据底座。
Apache Doris 2025 Roadmap:构建 GenAI 时代实时高效统一的数据底座
为什么 Apache Doris 是比 Elasticsearch 更好的实时分析替代方案?
本文将从技术选型的视角,从开放性、系统架构、实时写入、实时存储、实时查询等多方面,深入分析 Apache Doris 与 Elasticsearch 的能力差异及性能表现
为什么 Apache Doris 是比 Elasticsearch 更好的实时分析替代方案?
Apache Doris & SelectDB 技术能力全面解析
本文将对 Doris & SelectDB 适合的分析场景和技术能力进行概述解析
Apache Doris & SelectDB 技术能力全面解析
拉卡拉 x Apache Doris:统一金融场景 OLAP 引擎,查询提速 15 倍,资源直降 52%
拉卡拉早期基于 Lambda 架构构建数据系统面临存储成本高、实时写入性能差、复杂查询耗时久、组件维护复杂等问题。为此,拉卡拉选择使用 Apache Doris 替换 Elasticsearch、Hive、Hbase、TiDB、Oracle / MySQL 等组件,实现了 OLAP 引擎的统一、查询性能提升 15 倍、资源减少 52% 的显著成效。
拉卡拉 x Apache Doris:统一金融场景 OLAP 引擎,查询提速 15 倍,资源直降 52%
天翼云:Apache Doris + Iceberg 超大规模湖仓一体实践
天翼云基于 Apache Doris 成功落地项目已超 20 个,整体集群规模超 50 套,部署节点超 3000 个,存储容量超 15PB
天翼云:Apache Doris + Iceberg 超大规模湖仓一体实践
Apache Doris 2.1.9 版本正式发布
Apache Doris 2.1.9 版本正式发布,欢迎使用~

推荐镜像

更多
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等

登录插画

登录以查看您的控制台资源

管理云资源
状态一览
快捷访问