类型转换
在 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