ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

StarRocks `to_tera_timestamp` 函数详解:Teradata 风格时间字符串解析与转换指南

StarRocks `to_tera_timestamp` 函数详解:Teradata 风格时间字符串解析与转换指南 StarRocksto_tera_timestamp函数详解Teradata 风格时间字符串解析与转换指南【免费下载链接】starrocksThe worlds fastest open query engine for sub-second analytics both on and off the data lakehouse. With the flexibility to support nearly any scenario, StarRocks provides best-in-class performance for multi-dimensional analytics, real-time analytics, and ad-hoc queries. A Linux Foundation project.项目地址: https://gitcode.com/GitHub_Trending/st/starrocksto_tera_timestamp是 StarRocks 提供的一类日期时间函数它仿照 Teradata 数据库的日期时间格式约定将符合指定格式的字符串解析并转换为DATETIME类型值。对于需要从 Teradata 迁移 SQL、或处理非标准日期时间文本如04.1988,08、1988/04/08 2:3:4的 ETL 与数仓场景该函数提供了一种直接、可控的解析手段。读完本文你将掌握to_tera_timestamp的完整语法、全部格式元素、返回值与报错语义并从 StarRocks BE 源码层面理解其解析实现原理与测试验证方式。函数概述Teradata 兼容的时间解析入口to_tera_timestamp(str, format)的作用是按format指定的格式解析字符串str并将其转换为DATETIME值。它是 StarRocks 为兼容 Teradata及 Trino 生态中同名词法而设计的一组函数之一与其配套的还有返回DATE类型的to_tera_date。从源码结构看二者的实现完全同构在 be/src/exprs/time_functions.cpp 中to_tera_timestamp与to_tera_date共用同一个TeradataFormat解析器仅返回值类型不同前者TYPE_DATETIME后者TYPE_DATE。同时在 FE 端 Trino2SRFunctionCallTransformer.java 的 Trino 函数转换逻辑中同样映射了to_tera_timestamp说明该函数也承担着 Trino 语法兼容层的职责。语法DATETIME to_tera_timestamp(VARCHAR str, VARCHAR format)入参类型str与format均为VARCHAR。返回类型DATETIME。参数说明str待转换的时间表达式必须为VARCHAR类型。format用于解析str的时间格式描述符。format必须与str的实际内容匹配若二者不匹配函数返回NULL若format本身非法则返回错误。需要特别注意的是在 BE 实现中format参数必须是一个常量字面量。在 time_functions.cpp 的to_tera_timestamp_prepare阶段函数会调用context-is_notnull_constant_column(1)检查第 2 个参数是否为非常量否则直接返回NotSupported错误The 2rd argument must be literal。格式元素表下表列出了format支持的格式元素与官方文档一致ElementDescription[ \r \n \t - / , . ;]Punctuation characters that are ignored in conversionddDay of month (1 - 31)hhHour of day (1 - 12)hh24Hour of day (0 - 23)miMinute (0 - 59)mmMonth (01 - 12)ssSecond (0 - 59)yyyy4-digit yearyy2-digit yearamMeridian indicatorpmMeridian indicator几点解读标点符号空格、回车、换行、制表符、-、/、,、.、;在转换时被忽略因此你可以在格式串中自由使用它们充当分隔符甚至在解析时跳过字符串里对应位置的任意同类标点。hh是 12 小时制1–12需要配合am/pm使用才能正确表达下午时间hh24是 24 小时制0–23无需上午/下午指示符。mm与mi的区分mm表示月份monthmi表示分钟minute二者均以字母m开头使用时注意不要混淆。使用示例以下示例均来自官方文档可直接在 StarRocks 中执行验证-- 常见的 yyyy/mm/dd 顺序 select to_tera_timestamp(1988/04/08,yyyy/mm/dd); ----------------------------------------------- | to_tera_timestamp(1988/04/08, yyyy/mm/dd) | ----------------------------------------------- | 1988-04-08 00:00:00 | ----------------------------------------------- -- 美式 mm-dd-yyyy 顺序 select to_tera_timestamp(04-08-1988,mm-dd-yyyy); ----------------------------------------------- | to_tera_timestamp(04-08-1988, mm-dd-yyyy) | ----------------------------------------------- | 1988-04-08 00:00:00 | ----------------------------------------------- -- 任意标点分隔. 与 , 混用 select to_tera_timestamp(04.1988,08,mm.yyyy,dd); ----------------------------------------------- | to_tera_timestamp(04.1988,08, mm.yyyy,dd) | ----------------------------------------------- | 1988-04-08 00:00:00 | ----------------------------------------------- -- 12 小时制无 am/pm默认按上午处理 select to_tera_timestamp(1988/04/08 2,yyyy/mm/dd hh); ---------------------------------------------------- | to_tera_timestamp(1988/04/08 2, yyyy/mm/dd hh) | ---------------------------------------------------- | 1988-04-08 02:00:00 | ---------------------------------------------------- -- 24 小时制 select to_tera_timestamp(1988/04/08 14,yyyy/mm/dd hh24); ------------------------------------------------------- | to_tera_timestamp(1988/04/08 14, yyyy/mm/dd hh24) | ------------------------------------------------------- | 1988-04-08 14:00:00 | ------------------------------------------------------- -- 带分钟 select to_tera_timestamp(1988/04/08 14:15,yyyy/mm/dd hh24:mi); ------------------------------------------------------------- | to_tera_timestamp(1988/04/08 14:15, yyyy/mm/dd hh24:mi) | ------------------------------------------------------------- | 1988-04-08 14:15:00 | ------------------------------------------------------------- -- 秒的位数不需要严格对齐2、3、4 均为个位数输入 select to_tera_timestamp(1988/04/08 2:3:4,yyyy/mm/dd hh24:mi:ss); ---------------------------------------------------------------- | to_tera_timestamp(1988/04/08 2:3:4, yyyy/mm/dd hh24:mi:ss) | ---------------------------------------------------------------- | 1988-04-08 02:03:04 | ---------------------------------------------------------------- -- 12 小时制 am 指示符 select to_tera_timestamp(1988/04/08 02 am:3:4,yyyy/mm/dd hh am:mi:ss); --------------------------------------------------------------------- | to_tera_timestamp(1988/04/08 02 am:3:4, yyyy/mm/dd hh am:mi:ss) | --------------------------------------------------------------------- | 1988-04-08 02:03:04 | ---------------------------------------------------------------------源码实现原理TeradataFormat解析器剖析to_tera_timestamp的底层实现并不直接依赖strptime这类通用库而是由 StarRocks 自行实现的一个轻量级令牌解析器TeradataFormat完成。理解它的工作机制有助于你准确预判各种边界输入的行为。核心数据结构在 be/src/types/datetime_value.h 中定义了两个关键类型TeradataRuntimeState继承自DateTimeValue额外持有一个指向当前解析位置的指针valptr用于在多个令牌之间传递解析进度TeradataFormat内部维护一个_token_parsers向量std::vectorstd::functionbool(TeradataRuntimeState*, const char*)prepare阶段把格式串编译成一组令牌解析函数parse阶段逐行执行它们。整个生命周期与to_tera_timestamp的 prepare / close 钩子对应to_tera_timestamp_prepare中构造TeradataFormat并调用prepareto_tera_timestamp_close中释放状态见 time_functions.cpp。格式编译TeradataFormat::prepare在 datetime_value.cpp 中prepare逐字符扫描格式串并统计连续相同字符的重复次数repeat_count再依据字符归属的TeradataFormatChar枚举分支生成解析函数标点字符枚举T1–T10即-/,.;:空格\r\n\t生成匹配并跳过该字符的解析器若输入字符串当前位置不是该字符则解析失败ddd要求repeat_count 2否则视为非法格式解析 1–2 位数字写入_dayhhh / hh24要求repeat_count 2若其后紧跟字符2且再后跟4则识别为hh2424 小时制否则为hh12 小时制。这也解释了为何hh24能作为一个整体被识别——prepare在H分支内做了前缀匹配mmm / mirepeat_count 2时按月份解析写入_monthrepeat_count 1且下一个字符是i时按分钟解析写入_minute否则格式非法sss要求repeat_count 2解析秒写入_secondyyy / yyyyrepeat_count 2时按两位年解析并使用经典的百年规则int_value (int_value 70 ? 1900 : 2000)——即70–99映射到19xx00–69映射到20xxrepeat_count 4时按四位年解析aam要求其后必须紧跟m生成逐字符匹配a、m的解析器ppm要求其后必须紧跟m匹配成功后还会执行state-_hour 12将 12 小时制小时转换为 24 小时制其余字符一律视为非法格式prepare返回false最终表现为函数返回错误。从源码结构看prepare在函数执行前一次性完成格式校验与编译因此非法格式会在查询准备阶段即被拒绝而不是等到逐行解析时才暴露。逐行解析TeradataFormat::parse在 datetime_value.cpp 中parse对每行输入执行如下逻辑将TeradataRuntimeState的缺省字段初始化为_year 2000, _month 1, _day 1——这意味着格式串中未出现的日期字段会使用这些默认值依次调用_token_parsers中每个令牌解析函数任一失败即整体解析失败返回false解析成功后用状态中的年/月/日/时/分/秒/微秒构造DateTimeValue并输出。随后在 time_functions.cpp 的to_tera_timestamp主函数中通过ColumnViewerTYPE_VARCHAR逐行读取输入用ColumnBuilderTYPE_DATETIME构建结果列任意一行解析失败都只在该行位置追加NULL不会中断整批处理若整列输入均为NULL函数会提前短路返回RETURN_IF_COLUMNS_ONLY_NULL。返回值与报错语义综合文档与源码可以总结出如下边界行为输入情况结果format与str内容匹配返回解析得到的DATETIME值format与str内容不匹配如字符、顺序不符返回NULLformat为非法格式串含未知字符、重复次数不对返回错误在prepare阶段即被拒绝format为非字面量如来自普通列返回错误The 2rd argument must be literal输入str为NULL返回NULL未在格式串中声明的日期字段使用默认值补齐年2000、月1、日1从源码结构看时/分/秒缺省为 0一个典型的默认值行为示例来自测试用例to_tera_timestamp(1994, yyyy)会解析出1994-01-01 00:00:00——年来自输入月、日均取默认值。测试用例中还有;198804:08, ;yyyymm:dd这种以分号开头的输入验证了任意位置使用标点分隔符的灵活性。姊妹函数与周边生态to_tera_date与to_tera_timestamp共用同一TeradataFormat解析器但返回DATE类型见 time_functions.cpp。当日志或业务字段只需要日期部分、且数据源包含大量历史格式时它是更轻量的选择。Trino 兼容层FE 端的 Trino 函数转换器将 Trino 生态的to_tera_timestamp语法转换为 StarRocks 对应实现相关映射逻辑位于 Trino2SRFunctionCallTransformer.java并有对应的转换测试 TrinoFunctionTransformTest.java。因此从 Trino/Presto 迁移查询时这类函数名可以直接沿用。测试验证覆盖格式矩阵与边界输入该函数的正确性由参数化单元测试保证。在 be/test/exprs/time_functions_test.cpp 的ToTimestampTestFixture中通过INSTANTIATE_TEST_SUITE_P注入 12 组(输入字符串, 格式串, 期望值)用例覆盖了不同字段顺序yyyy-mm-dd、mm-dd-yyyy、mm.yyyy,dd混合标点;198804:08分号打头、04.1988,0824 小时制与 12 小时制hh24与hh am、hh pm个位数时/分/秒的宽松解析2:3:4→02:03:04pm 转换验证1988/04/08 2 pm:3:4→1988-04-08 14:03:04直接验证了_hour 12的进位逻辑。测试还显式走完prepare → execute → close全流程并断言结果列类型为DATETIMEresult-is_timestamp()与文档声明的返回值一致。除 BE 单测外该函数也通过to_tera_date的测试用例如1994, yyyy→1994-01-01间接覆盖了默认值补齐行为。小结to_tera_timestamp是 StarRocks 在时间解析领域的格式自描述方案它用一套简洁的 Teradata 风格格式元素yyyy/yy/mm/dd/hh/hh24/mi/ss/am/pm及可忽略标点覆盖绝大多数文本日期表达同时具备严格的格式校验、精确到秒的解析能力和友好的NULL容错语义。结合 BE 端TeradataFormat的实现与完备的参数化测试无论是迁移旧系统 SQL、清洗异构日志时间字段还是对接 Trino 生态查询它都是一个稳定且值得优先选用的解析函数。【免费下载链接】starrocksThe worlds fastest open query engine for sub-second analytics both on and off the data lakehouse. With the flexibility to support nearly any scenario, StarRocks provides best-in-class performance for multi-dimensional analytics, real-time analytics, and ad-hoc queries. A Linux Foundation project.项目地址: https://gitcode.com/GitHub_Trending/st/starrocks创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表