StarRocks positive() 数学函数详解:语法、数据类型支持与源码实现原理
【免费下载链接】starrocksThe world's 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
positive(x)是 StarRocks 提供的一元数学函数,功能是将输入值原样返回,不做任何数学变换。本文以官方函数文档为主体,结合 StarRocks 开源仓库中的函数注册表与 BE 端向量化实现源码,深入讲解positive()的语法、参数类型约束、返回值规则、使用示例及其底层实现原理,并与其姊妹函数negative()进行对照,帮助你准确理解这一恒等(identity)运算在查询中的真实行为与适用场景。
函数概述
positive(x)返回参数x本身的值,属于一元恒等函数。从语义上看,它不改变数值的大小与符号,其作用更偏向于"显式声明数值为正"或在泛型/模板化查询中保持某种数值类型路径的一致。
在官方文档(positive.md)中,其定位被描述为:
Returns
xas a value.
即:返回x作为一个值。
语法
POSITIVE(x);- 函数名大小写不敏感,
positive与POSITIVE等价; - 参数个数固定为 1,传入多于或少于一个参数都会导致语法或函数匹配错误;
- 该函数同时适用于列、常量字面量以及表达式,例如
positive(column_a)、positive(3)、positive(1 + 2)均合法。
参数与数据类型支持
参数x支持以下 6 种数据类型:
| 数据类型 | 说明 |
|---|---|
BIGINT | 64 位有符号整数 |
DOUBLE | 双精度浮点数 |
DECIMALV2 | StarRocks 传统高精度定点数类型 |
DECIMAL32 | 32 位精度定点数 |
DECIMAL64 | 64 位精度定点数 |
DECIMAL128 | 128 位精度定点数 |
这一支持范围在 FE 端的函数注册表中有完整的对应记录。在 gensrc/script/functions.py 中,positive函数注册了 6 个重载(函数 ID 10260 ~ 102622),分别映射到 BE 端MathFunctions::positive模板的不同实例化:
positive(DOUBLE) -> DOUBLEpositive(BIGINT) -> BIGINTpositive(DECIMALV2) -> DECIMALV2positive(DECIMAL32) -> DECIMAL32positive(DECIMAL64) -> DECIMAL64positive(DECIMAL128) -> DECIMAL128
需要注意:
positive并不支持INT、SMALLINT、TINYINT、FLOAT、LARGEINT等其他数值类型。若直接对这些类型调用positive(),StarRocks 会因找不到匹配的函数签名而报错。此时需要先使用CAST显式转换为上述 6 种类型之一,例如positive(cast(int_col as bigint))。
返回值
positive(x)返回一个值与x的数据类型完全相同,即函数不改变数值的精度与标度(scale),是严格的一元恒等变换。
这与函数底层实现是一致的:在 BE 端向量化实现中,positive对输入列直接进行"可变引用返回",不做任何逐元素计算(详见下文"源码实现原理"一节)。
示例
以下示例来自官方文档,可直接在 StarRocks 的 MySQL 客户端中执行验证。
示例一:BIGINT 常量
mysql> select positive(3); +-------------+ | positive(3) | +-------------+ | 3 | +-------------+ 1 row in set (0.01 sec)positive(3)将整数3原样返回。
示例二:DECIMALV2 常量
mysql> select positive(cast(3.14 as decimalv2)); +--------------------------------------+ | positive(CAST(3.14 AS DECIMAL(9,0))) | +--------------------------------------+ | 3.14 | +--------------------------------------+ 1 row in set (0.01 sec)可以看到,虽然 FE 端在结果列标题中按照 DECIMALV2 的默认显示形式将CAST(3.14 AS DECIMALV2)展示为DECIMAL(9,0),但函数实际返回的数值仍完整保留为3.14,小数部分未丢失、符号未改变,进一步印证了positive保持输入类型与数值原样返回的特性。
与 negative() 的对照
理解positive的最好方式是与它的镜像函数negative()对照,两者的文档结构、类型支持完全对称:
negative(x)返回x的相反数,例如negative(3)的结果为-3;positive(x)返回x本身,例如positive(3)的结果为3;- 两者支持完全相同的数据类型集合(BIGINT、DOUBLE、DECIMALV2、DECIMAL32、DECIMAL64、DECIMAL128)。
在 gensrc/script/functions.py 中,negative的 6 个重载(函数 ID 10270 ~ 102722)紧邻positive注册,一一对应;官方文档 negative.md 亦与之呼应。
源码实现原理
1. FE 端函数注册
positive是一个内建标量函数,其函数签名(function signature)在 gensrc/script/functions.py 中集中注册,构建时通过 StarRocks 的代码生成管线产出 FE 与 BE 两侧的函数元数据。每种支持的类型各对应一个独立的函数 ID 与 BE 实现入口,例如:
[10260, "positive", True, False, "DOUBLE", ["DOUBLE"], "MathFunctions::positive<TYPE_DOUBLE>"], [10261, "positive", True, False, "BIGINT", ["BIGINT"], "MathFunctions::positive<TYPE_BIGINT>"], [10262, "positive", True, False, "DECIMALV2", ["DECIMALV2"], "MathFunctions::positive<TYPE_DECIMALV2>"], [102620, "positive", True, False, "DECIMAL32", ["DECIMAL32"], "MathFunctions::positive<TYPE_DECIMAL32>"], [102621, "positive", True, False, "DECIMAL64", ["DECIMAL64"], "MathFunctions::positive<TYPE_DECIMAL64>"], [102622, "positive", True, False, "DECIMAL128", ["DECIMAL128"], "MathFunctions::positive<TYPE_DECIMAL128>"],上述每一行都声明了"入参类型 -> 返回类型"完全一致,这正是文档中"返回类型与输入类型相同"这一规则在实现层面的直接体现。
2. BE 端向量化实现
在 BE 端,positive的向量化实现位于 be/src/exprs/math_functions.h:
template <LogicalType Type> DEFINE_VECTORIZED_FN(positive) { return std::move(*columns[0]).mutate(); }其实现极为精简:std::move(*columns[0]).mutate()直接取得输入列columns[0]的所有权并返回其可变版本,不执行任何数值运算。也就是说,positive在 StarRocks 的向量化执行引擎中是一个零开销的恒等操作(identity operation),不会引入额外的计算或数据拷贝开销。
与之对照,同一文件中的negative实现则不同:
template <LogicalType Type> DEFINE_VECTORIZED_FN(negative) { if constexpr (lt_is_decimal<Type>) { const auto& type = context->get_return_type(); return VectorizedStrictUnaryFunction<negativeImpl>::evaluate<Type>(VECTORIZED_FN_ARGS(0), type.precision, type.scale); } else { return VectorizedStrictUnaryFunction<negativeImpl>::evaluate<Type>(VECTORIZED_FN_ARGS(0)); } }negative通过negativeImpl对每个元素取相反数;对于定点数类型还会传入precision与scale,以保证负数转换时精度与标度不被破坏。而positive连这一步都省去了——从源码结构可以推断,positive本质上是一个为保持"一元函数调用形态一致性"而提供的语义占位符,它在执行层直接透传数据。
典型使用场景与注意事项
- 类型保持的显式声明:在需要明确"数值为正"语义或希望与其他一元数学函数保持调用形式一致时,可使用
positive(col); - 通用函数/模板化 SQL 的占位:在自动生成的 SQL 或函数包装层中,
positive可作为恒等映射占位,避免对"正数情况"单独写分支; - 类型约束:仅支持文档列出的 6 种类型,使用其他数值类型前需显式
CAST; - 性能:由于 BE 端实现为直接透传列,
positive对查询性能几乎无影响,可以放心用于大数据量列; - NULL 语义:
positive为恒等函数,输入NULL时结果仍为NULL(与大多数标量函数保持一致),实际使用时建议结合COALESCE或IFNULL处理空值场景。
延伸阅读
- StarRocks 数学函数索引:查看完整的数学函数清单;
- negative 函数文档:
positive的镜像函数,返回输入值的相反数; - 函数注册表实现:
positive/negative等内建标量函数的签名定义来源; - BE 端数学函数向量化实现:包含
positive、negative及大量其他数学函数的底层执行逻辑。
【免费下载链接】starrocksThe world's 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),仅供参考