类型转换
在 Doris 中,每个表达式均有其类型(例如 select 1, col1, from_unixtime(col2) from table1
中的 1
,col1
,from_unixtime(col2)
等)。将一个表达式从一种类型转换到另一种类型的过程称为“类型转换”。
类型转换会在两种情况下发生,一是显式转换,二是隐式转换。
所有类型转换均遵守特定的规则。我们根据转换的目标类型分类描述相关规则。例如,从 INT
转换到 DOUBLE
和 从 STRING
转换到 DOUBLE
,均在 转换为 FLOAT/DOUBLE 文档中描述。
转换是否能发生,以及转换的结果是否为 Nullable 类型,与是否开启严格模式有关(session variable enable_strict_cast
)。一般来说,当开启严格模式时,转换失败的数据将会立即引发报错导致 SQL 失败。当关闭严格模式时,转换失败的数据行结果为 NULL
。
显式转换
显式转换通过 CAST
函数进行,例如:
CAST(1.23 as INT)
将数字 1.23 转换为 INT 类型。
CAST(colA as DATETIME(6))
将列/表达式 colA 转换为 DATETIME(6) 类型(即拥有微秒精度的 DATETIME 类型)。
以下分别描述在严格模式(enable_strict_cast = true
)和非严格模式(enable_strict_cast = false
)下,类型之间的转换关系。包括以下四种情况:
符号 | 含义 |
---|---|
x | 不允许转换 |
P | 当入参已经为 Nullable 类型时,返回类型才会为 Nullable,即该转换不会将非 Null 值转换为 Null |
A | 返回类型总是为 Nullable 类型。即该转换有可能将非 Null 值转换为 Null |
O | 当输入类型转换到输出类型可能溢出时,返回类型总是为 Nullable 类型。对于非 Null 值输入,如果转换实际导致溢出,该转换结果可能为 Null |
具体的类型转换规则与 Nullable 属性,请查看当前目录下的各个类型转换文档。
严格模式
From\To | bool | tinyint | smallint | int | bigint | largeint | float | double | decimal | date | datetime | time | IPv4 | IPv6 | char | varchar | string | bitmap | hll | json | array | map | struct | variant |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
bool | P | P | P | P | P | P | P | P | P | x | x | x | x | x | x | x | P | x | x | x | ||||
tinyint | P | P | P | P | P | P | P | P | P | P | P | P | x | x | x | x | P | x | x | x | ||||
smallint | P | P | P | P | P | P | P | P | P | P | P | P | x | x | x | x | P | x | x | x | ||||
int | P | P | P | P | P | P | P | P | P | P | P | P | x | x | x | x | P | x | x | x | ||||
bigint | P | P | P | P | P | P | P | P | P | P | P | P | x | x | x | x | P | x | x | x | ||||
largeint | P | P | P | P | P | P | P | P | P | P | P | P | x | x | x | x | P | x | x | x | ||||
float | P | P | P | P | P | P | P | P | P | P | P | P | x | x | x | x | P | x | x | x | ||||
double | P | P | P | P | P | P | P | P | P | P | P | P | x | x | x | x | P | x | x | x | ||||
decimal | P | P | P | P | P | P | P | P | P | P | P | P | x | x | x | x | P | x | x | x | ||||
date | x | x | x | P | P | P | x | x | x | P | P | x | x | x | x | x | x | x | x | x | ||||
datetime | x | x | x | x | P | P | x | x | x | P | P | P | x | x | x | x | x | x | x | x | ||||
time | x | P | P | P | P | P | x | x | x | P | P | P | x | x | x | x | x | x | x | x | ||||
IPv4 | x | x | x | x | x | x | x | x | x | x | x | x | P | P | x | x | x | x | x | x | ||||
IPv6 | x | x | x | x | x | x | x | x | x | x | x | x | x | P | x | x | x | x | x | x | ||||
char | P | P | P | P | P | P | P | P | P | P | P | P | P | P | x | x | P | P | P | P | ||||
varchar | P | P | P | P | P | P | P | P | P | P | P | P | P | P | x | x | P | P | P | P | ||||
string | P | P | P | P | P | P | P | P | P | P | P | P | P | P | x | x | P | P | P | P | ||||
bitmap | x | x | x | x | x | x | x | x | x | x | x | x | x | x | x | x | x | P | x | x | x | x | x | |
hll | x | x | x | x | x | x | x | x | x | x | x | x | x | x | x | x | x | x | P | x | x | x | x | |
json | A | A | A | A | A | A | A | A | A | x | x | x | x | x | A | A | A | x | x | P | A | x | A | |
array | x | x | x | x | x | x | x | x | x | x | x | x | x | x | x | x | P | P | x | x | ||||
map | x | x | x | x | x | x | x | x | x | x | x | x | x | x | x | x | x | x | P | x | ||||
struct | x | x | x | x | x | x | x | x | x | x | x | x | x | x | x | x | P | x | x | P | ||||
variant |
非严格模式
From\To | bool | tinyint | smallint | int | bigint | largeint | float | double | decimal | date | datetime | time | IPv4 | IPv6 | char | varchar | string | bitmap | hll | json | array | map | struct | variant |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
bool | P | P | P | P | P | P | P | P | O | x | x | x | x | x | x | x | P | x | x | x | ||||
tinyint | P | P | P | P | P | P | P | P | O | A | A | A | x | x | x | x | P | x | x | x | ||||
smallint | P | A | P | P | P | P | P | P | O | A | A | A | x | x | x | x | P | x | x | x | ||||
int | P | A | A | P | P | P | P | P | O | A | A | A | x | x | x | x | P | x | x | x | ||||
bigint | P | A | A | A | P | P | P | P | O | A | A | A | x | x | x | x | P | x | x | x | ||||
largeint | P | A | A | A | A | P | P | P | O | A | A | A | x | x | x | x | P | x | x | x | ||||
float | P | A | A | A | A | A | P | P | A | A | A | A | x | x | x | x | P | x | x | x | ||||
double | P | A | A | A | A | A | P | P | A | A | A | A | x | x | x | x | P | x | x | x | ||||
decimal | P | O | O | O | O | O | P | P | O | A | A | A | x | x | x | x | P | x | x | x | ||||
date | x | x | x | P | P | P | P | P | x | P | P | x | x | x | x | x | x | x | x | x | ||||
datetime | x | x | x | x | P | P | P | P | x | P | A | P | x | x | x | x | x | x | x | x | ||||
time | x | A | A | A | P | P | P | P | x | P | P | A | x | x | x | x | x | x | x | x | ||||
IPv4 | x | x | x | x | x | x | x | x | x | x | x | x | P | P | x | x | x | x | x | x | ||||
IPv6 | x | x | x | x | x | x | x | x | x | x | x | x | x | P | x | x | x | x | x | x | ||||
char | A | A | A | A | A | A | A | A | A | A | A | A | A | A | x | x | A | A | A | A | ||||
varchar | A | A | A | A | A | A | A | A | A | A | A | A | A | A | x | x | A | A | A | A | ||||
string | A | A | A | A | A | A | A | A | A | A | A | A | A | A | x | x | A | A | A | A | ||||
bitmap | x | x | x | x | x | x | x | x | x | x | x | x | x | x | x | x | x | P | x | x | x | x | x | |
hll | x | x | x | x | x | x | x | x | x | x | x | x | x | x | x | x | x | x | P | x | x | x | x | |
json | A | A | A | A | A | A | A | A | A | x | x | x | x | x | A | A | A | x | x | P | A | x | A | |
array | x | x | x | x | x | x | x | x | x | x | x | x | x | x | x | x | P | P | x | x | ||||
map | x | x | x | x | x | x | x | x | x | x | x | x | x | x | x | x | x | x | P | x | ||||
struct | x | x | x | x | x | x | x | x | x | x | x | x | x | x | x | x | P | x | x | P | ||||
variant |
隐式转换
隐式转换是在某种情况下,输入 SQL 中未指明,但 Doris 自动规划产生的 CAST 表达式。主要产生于:
- 函数调用时,给定实参类型与函数签名类型不匹配
- 数学表达式两侧类型不一致
等场景。
转换矩阵
TODO
公共类型
在因作为数学运算的操作数而需要发生隐式转换时,首先要确定转换的公共类型。两侧操作数如果与公共类型不一致,则会各自规划到公共类型的 CAST 表达式。
TODO