StarRocks bit_shift_left 函数详解:算术左移的语法、边界行为与底层实现
【免费下载链接】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
bit_shift_left是 StarRocks 提供的位运算函数之一,用于将数值表达式的二进制表示按指定位数向左移动,实现高效的算术左移(arithmetic left shift)计算。本指南以官方函数参考文档为主体,结合 FE(Frontend)解析与 BE(Backend)执行两端的源码实现,完整讲解其语法、参数类型、返回值、边界规则与实战示例,帮助你准确理解位长度不变、低位补 0、高位保持等语义,并将其正确应用于权限掩码、状态标志位、哈希计算等场景。
功能概述
bit_shift_left(value, shift)将value的二进制表示向左移动shift位。这是一个算术左移操作,其核心特征包括:
- 位长度不变:移位过程不会改变二进制串的总位数,移出的高位直接丢弃;
- 低位补 0:右端空出的低位统一补 0;
- 高位保持原值:原有高位在丢弃后,其符号位含义不受影响。
例如,将二进制10101左移一位得到11010(等价于十进制21 → 42,即乘以 2)。
从源码结构看,该函数在 StarRocks 中归属于算术运算(Arithmetic)体系,与加、减、乘、除以及bitand、bitor、bitxor、bitnot等位运算并列。在 BE 端实现中,BitShiftLeftOp与BitShiftRightOp、BitShiftRightLogicalOp一同被定义并注册为二进制运算算子,参见 be/src/exprs/arithmetic_operation.h;在 FE 端,FunctionSet中声明了BIT_SHIFT_LEFT = "bit_shift_left"等函数名常量,参见 fe/fe-core/src/main/java/com/starrocks/catalog/FunctionSet.java。
语法
bit_shift_left(value, shift)该函数接受两个参数,返回移位后的结果。
参数说明
| 参数 | 说明 | 支持的数据类型 |
|---|---|---|
value | 待移位的数值或数值表达式 | TINYINT、SMALLINT、INT、BIGINT、LARGEINT |
shift | 左移的位数 | BIGINT |
返回值
返回与value相同类型的结果值。例如,value为 INT,返回类型即为 INT;value为 LARGEINT,则返回 LARGEINT。
使用说明与边界行为
- NULL 传播:任一输入参数为 NULL,函数返回 NULL。
- 负移位位数:若
shift小于 0,返回 0。 - 移位位数为 0:将
value左移 0 位,结果恒为原value。 - 对 0 移位:将 0 左移任意位数,结果恒为 0。
- 非整数数值类型:若
value为数值类型但不是整数(如浮点数),会被强制转换为整数后再执行移位。参见 示例。 - 字符串类型:若
value为字符串,则尽可能转换为整数;若无法转换,则按 NULL 处理。参见 示例。
这些规则在 SQL 层保证了对异常输入的确定性输出,避免了移位位数为负、类型不匹配等场景下的未定义行为。
示例
以下示例均在 StarRocks 中执行并验证:
SELECT bit_shift_left(2, 1); +----------------------+ | bit_shift_left(2, 1) | +----------------------+ | 4 | +----------------------+2的二进制表示为10,左移一位得到100,即十进制4。
SELECT bit_shift_left(2.2, 1); +------------------------+ | bit_shift_left(2.2, 1) | +------------------------+ | 4 | +------------------------+2.2先被转换为整数2,再左移一位得到4。
SELECT bit_shift_left("2", 1); +------------------------+ | bit_shift_left('2', 1) | +------------------------+ | 4 | +------------------------+字符串"2"可被转换为整数2,左移一位得到4。
SELECT bit_shift_left(-2, 1); +-----------------------+ | bit_shift_left(-2, 1) | +-----------------------+ | -4 | +-----------------------+负数同样支持算术左移:-2的二进制补码表示左移一位得到-4,等价于乘以 2。这印证了文档中"位长度不变、低位补 0"的算术左移语义——符号位不因移位而改变结果的符号。
实战场景:位掩码与标志位
bit_shift_left最常见的实战价值在于快速构造位掩码(bitmask)和状态标志位:
- 构造权限掩码:
bit_shift_left(1, n)可生成第n位为 1 的掩码,例如bit_shift_left(1, 3)得到8(二进制1000),用于权限系统的位级授权判断。 - 快速乘 2 的幂:左移一位等价于乘以 2,
bit_shift_left(value, n)等价于value * 2^n,在需要以 2 的幂进行缩放时可替代乘法运算。 - 与位运算函数配合:可与
bitand、bitor等函数组合使用,实现位字段的读写。相关函数文档位于同目录下的 bitand、bitor、bitnot 等。
底层实现原理
FE 端:函数注册与执行算子映射
从 FE 源码结构看,bit_shift_left的调用链完整覆盖了 SQL 解析、表达式构建与执行算子下发的各个环节:
- 函数名注册:
FunctionSet中声明函数名常量BIT_SHIFT_LEFT,参见 fe/fe-core/src/main/java/com/starrocks/catalog/FunctionSet.java; - 表达式构建:在
ScalarOperatorToExpr中,case "bit_shift_left"分支将其构建为ArithmeticExpr,并绑定ArithmeticExpr.Operator.BIT_SHIFT_LEFT,参见 fe/fe-core/src/main/java/com/starrocks/sql/plan/ScalarOperatorToExpr.java; - 算子下发:
ScalarOperatorToExecExpr通过buildArithmetic将其转换为执行表达式,参见 fe/fe-core/src/main/java/com/starrocks/sql/plan/ScalarOperatorToExecExpr.java; - Opcode 映射:
ExprOpcodeRegistry将ArithmeticExpr.Operator.BIT_SHIFT_LEFT映射为 thrift 层 opcodeTExprOpcode.BIT_SHIFT_LEFT,参见 fe/fe-core/src/main/java/com/starrocks/sql/expression/ExprOpcodeRegistry.java; - Decimal 类型限制:
DecimalV3FunctionAnalyzer将BIT_SHIFT_LEFT归入不支持 Decimal 参数分析的函数集合,即该函数不接受 DECIMAL 类型直接参与,参见 fe/fe-core/src/main/java/com/starrocks/sql/analyzer/DecimalV3FunctionAnalyzer.java。
BE 端:算子定义与移位执行
BE 端将位运算统一实现在算术运算模板中:
- 算子定义:
BitShiftLeftOp等结构体定义了移位算子,并通过TYPE_GUARD注册类型守卫,参见 be/src/exprs/arithmetic_operation.h; - 算子名称:
get_op_name模板函数返回"bit_shift_left"等可读名称,参见 be/src/exprs/arithmetic_operation.h; - 核心移位逻辑:在
ArithmeticBinaryOperator::apply中,is_bit_shift_left_op<Op>分支直接执行 C++ 左移运算l << r,参见 be/src/exprs/arithmetic_operation.h。由于返回类型与value类型保持一致(ReturnType<Type, ResultType>约束),因此左移产生的溢出高位会被丢弃,符合文档所述"位长度不变"的语义。
与 Trino 函数的兼容映射
StarRocks 的 Trino 方言解析器将 Trino 的bitwise_left_shift函数自动转换为bit_shift_left,便于从 Trino 迁移 SQL 的用户无缝使用,参见 fe/fe-core/src/main/java/com/starrocks/connector/parser/trino/Trino2SRFunctionCallTransformer.java。
相关函数
- bit_shift_right:算术右移,高位补符号位。
- bit_shift_right_logical:逻辑右移,高位补 0。
三个移位函数在 BE 端共享同一套算术算子框架(见 be/src/exprs/arithmetic_operation.h),区别仅在于右移时是补符号位(算术右移)还是补 0(逻辑右移),而左移始终低位补 0,三者共同构成了完整的位级移位能力。
总结
bit_shift_left是 StarRocks 内置的算术左移位函数,支持 TINYINT 到 LARGEINT 的整数类型,并具备 NULL 传播、负位数返回 0、类型自动转换等明确边界规则。从源码层面看,其执行链路从 FE 的FunctionSet注册、ArithmeticExpr构建,到 BE 的BitShiftLeftOp模板实例化与 C++ 左移运算,完整闭环且与 Trino 方言兼容。在 SQL 中合理使用bit_shift_left,可以高效实现位掩码构造、乘以 2 的幂等运算,是 StarRocks 位运算能力中的重要一环。
【免费下载链接】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),仅供参考