• flink-sql所有数据类型-1.15


    1. 版本说明

    本文档内容基于flink-1.15.x,其他版本的整理,请查看本人博客的 flink 专栏其他文章。

    2. 介绍

    Flink SQL有一组丰富的本地数据类型可供用户使用。

    数据类型描述表生态系统中值的逻辑类型,它可用于声明操作的输入和/或输出类型。

    Flink的数据类型类似于SQL标准的数据类型,但也包含了关于值是否为空的信息,以便有效地处理标量表达式。

    数据类型的例子有:

    • INT
    • INT NOT NULL
    • INTERVAL DAY TO SECOND(3)
    • ROW, myOtherField TIMESTAMP(3)>

    所有预定义的数据类型在下面列出。

    2.1. Table API 中的数据类型

    java/scala

    基于 JVM 的用户,在使用 Table API 或者是自定义连接器、catalog、自定义函数时,可以使用 org.apache.flink.table.types.DataType 类的实例。

    DataType 实例有两个职责:

    1. 声明一个逻辑类型:这并不是定义传输或存储的具体物理表示,但其定义了基于 jvm/Python 语言和表生态系统之间的边界。
    2. 可选:将数据的物理表示提示给 planner 计划器,这对于其他 API 是非常有用的。

    为了流畅的使用 API ,可以在表程序开头添加 import 语句导入所有的数据类型。

    java

    import static org.apache.flink.table.api.DataTypes.*;
    DataType t = INTERVAL(DAY(), SECOND(3));
    
    • 1
    • 2

    scala

    import org.apache.flink.table.api.DataTypes._
    val t: DataType = INTERVAL(DAY(), SECOND(3));
    
    • 1
    • 2

    2.1.1. 物理提示

    基于sql的类型系统末端的表生态系统边缘需要物理提示,并且是编程代码指定的数据类型。提示表示所期望的数据格式。

    例如,数据源使用 java.sql.Timestamp 类来生成逻辑时间戳值,而不是使用 java.time.LocalDateTime,后者是默认值。有了这些信息,程序运行时就可以将生成的类转换为它的内部数据格式。同时,sink 也可以声明它从运行时获取到的数据格式。

    下面是一些如何声明桥接转换类的例子:

    java

    // 告诉运行时使用 java.sql.Timestamp 而不是 java.time.LocalDateTime 实例
    DataType t = DataTypes.TIMESTAMP(3).bridgedTo(java.sql.Timestamp.class);
    
    // 告诉运行时使用原生的 int 数组而不是包装的 integer 数组
    DataType t = DataTypes.ARRAY(DataTypes.INT().notNull()).bridgedTo(int[].class);
    
    • 1
    • 2
    • 3
    • 4
    • 5

    scala

    // 告诉运行时使用 java.sql.Timestamp 而不是 java.time.LocalDateTime 实例
    val t: DataType = DataTypes.TIMESTAMP(3).bridgedTo(classOf[java.sql.Timestamp]);
    
    // 告诉运行时使用原生的 int 数组而不是包装的 integer 数组
    val t: DataType = DataTypes.ARRAY(DataTypes.INT().notNull()).bridgedTo(classOf[Array[Int]]);
    
    • 1
    • 2
    • 3
    • 4
    • 5

    注意:通常来说,只有在扩展 API 时才要求物理提示。用户在自定义 sources/sinks/functions 时并不需要定义这些提示。表程序中的提示(比如:field.cast(TIMESTAMP(3).bridgedTo(Timestamp.class)))将会被忽略。

    下面将列出所有预定义数据类型。

    默认的计划器支持下面的SQL类型

    java/scala

    数据类型解释
    CHAR
    VARCHAR
    STRING
    BOOLEAN
    BYTES支持BINARY 和VARBINARY
    DECIMAL支持固定的精度和刻度
    TINYINT
    SMALLINT
    INTEGER
    BIGINT
    FLOAT
    DOUBLE
    DATE
    TIME只支持精度:0
    TIMESTAMP
    TIMESTAMP_LTZ
    INTERVAL只支持 interval of MONTHSECOND(3)
    ARRAY
    MULTISET
    MAP
    ROW
    RAW
    structured types目前仅可在自定义函数中使用

    3. 列出所有数据类型

    该章节会列出所有预定义的数据类型。

    java/scala

    对于基于 JVM 的 Table API ,在 org.apache.flink.table.api.DataTypes 中的类型都已经可以使用了。

    3.1. Character Strings

    3.1.1. CHAR

    固定长度的character string。

    SQL

    CHAR
    CHAR(n)
    
    • 1
    • 2

    java/scala

    DataTypes.CHAR(n);
    
    • 1

    桥接到JVM数据类型

    Java 类型InputOutputOutput
    java.lang.StringXX默认
    byte[]XXUTF-8编码
    org.apache.flink.table.data.StringDataXX内部数据结构

    该类型可以使用CHAR(n)声明,其中n是字符的数量。n的值必须在12147,483,647之间(前后都包括)。如果没有指定长度,则n等于1。

    3.1.2. VARCHAR/STRING

    可变长度的character string。

    SQL

    VARCHAR
    VARCHAR(n)
    
    STRING
    
    • 1
    • 2
    • 3
    • 4

    java/scala

    DataTypes.VARCHAR(n);
    DataTypes.STRING();
    
    • 1
    • 2

    桥接到JVM数据类型

    Java 类型InputOutputOutput
    java.lang.StringX默认
    byte[]XXUTF-8编码
    org.apache.flink.table.data.StringDataXX内部数据结构

    该类型可以使用VARCHAR(n)声明,其中n是最大的字符数量。N的值必须在12147,483,647之间(包括两者)。如果没有指定长度,则n等于1。

    STRINGVARCHAR(2147483647)相同。

    3.2. Binary Strings

    BINARY

    固定长度的二进制字符串,等同于字节序列。

    SQL

    BINARY
    BINARY(n)
    
    • 1
    • 2

    java/scala

    DataTypes.BINARY(n);
    
    • 1

    桥接到JVM数据类型

    Java 类型InputOutputOutput
    byte[]XX默认

    该类型可以使用BINARY(n)声明,其中n为字节数。N的值必须在12147,483,647之间(包括两者)。如果没有指定长度,则n等于1。

    3.2.1. VARBINARY/BYTES

    可变长度的二进制字符串,等同于字节序列。

    SQL

    VARBINARY
    VARBINARY(n)
    
    BYTES
    
    • 1
    • 2
    • 3
    • 4

    java/scala

    DataTypes.VARBINARY(n);
    DataTypes.BYTES();
    
    • 1
    • 2

    桥接到JVM数据类型

    Java 类型InputOutputOutput
    byte[]XX默认

    该类型可以使用VARBINARY(n)声明,其中n为最大字节数。N的值必须在12147,483,647之间(包括两者)。如果没有指定长度,则n等于1。

    BYTESVARBINARY(2147483647)相同。

    3.3. 精确数字

    3.3.1. DECIMAL

    具有固定精度和比例的小数的数据类型。

    SQL

    DECIMAL
    DECIMAL(p)
    DECIMAL(p, s)
    
    DEC
    DEC(p)
    DEC(p, s)
    
    NUMERIC
    NUMERIC(p)
    NUMERIC(p, s)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    java/scala

    DataTypes.DECIMAL(p,s);
    
    • 1

    桥接到JVM数据类型

    Java 类型InputOutputOutput
    java.math.BigDecimalXX默认
    org.apache.flink.table.data.DecimalDataXX内部数据结构

    该类型可以使用DECIMAL(p, s)声明,其中p是数字(精度)的总位数,s是数字(刻度)小数点右边的位数。
    P的值必须在138之间(包括两者)。S的值必须在0p之间(包括两者)。p的默认值是10。s的默认值是0。

    NUMERIC(p, s)DEC(p, s)和该类型含义一样。

    3.3.2. TINYINT

    值从-128127,1个字节,有符号整数。

    SQL

    TINYINT
    
    • 1

    java/scala

    DataTypes.TINYINT();
    
    • 1

    桥接到JVM数据类型

    Java 类型InputOutputOutput
    java.lang.ByteXX默认
    byteX(X)类型为非空null时才会输出

    3.3.3. SMALLINT

    值从-32,76832,767,2个字节,有符号整数。

    SQL

    SMALLINT
    
    • 1

    java/scala

    DataTypes.SMALLINT();
    
    • 1

    桥接到JVM数据类型

    Java 类型InputOutputOutput
    java.lang.ShortXX默认
    shortX(X)类型为非空null时才会输出

    3.3.4. INT

    值从-2147,483,6482147,483,647,4个字节,有符号整数。

    SQL

    INT
    INTEGER
    
    • 1
    • 2

    java/scala

    DataTypes.INT();
    
    • 1

    桥接到JVM数据类型

    Java 类型InputOutputOutput
    java.lang.IntegerXX默认
    intX(X)类型为非空null时才会输出

    INTEGER也表示该类型。

    3.3.5. BIGINT

    值从-9,223,372,036,854,775,8089,223,372,036,854,775,807,8个字节,有符号整数。

    SQL

    BIGINT
    
    • 1

    java/scala

    DataTypes.BIGINT();
    
    • 1

    桥接到JVM数据类型

    Java 类型InputOutputOutput
    java.lang.LongXX默认
    longX(X)类型为非空null时才会输出

    3.4. 近似数字

    3.4.1. FLOAT

    4个字节的单精度浮点数。

    与SQL标准相比,该类型不带参数。

    SQL

    FLOAT
    
    • 1

    java/scala

    DataTypes.FLOAT();
    
    • 1

    桥接到JVM数据类型

    Java 类型InputOutputOutput
    java.lang.FloatXX默认
    floatX(X)类型为非空null时才会输出

    3.4.2. DOUBLE

    8字节的双精度浮点数。

    SQL

    DOUBLE
    DOUBLE PRECISION
    
    • 1
    • 2

    java/scala

    DataTypes.DOUBLE();
    
    • 1

    桥接到JVM数据类型

    Java 类型InputOutputOutput
    java.lang.DoubleXX默认
    doubleX(X)类型为非空null时才会输出

    DOUBLE PRECISION也表示该类型。

    3.5. Date 和Time

    注意:所有时间类型的精度 p 指的都是秒后面的小数个数。

    3.5.1. DATE

    日期数据类型为年-月-日,取值范围为0000-01-01 ~ 9999-12-31

    与 SQL 标准相比,范围从 0000 年开始。

    SQL

    DATE
    
    • 1

    java/scala

    DataTypes.DATE();
    
    • 1

    桥接到JVM数据类型

    Java 类型InputOutputOutput
    java.time.LocalDateXX默认
    java.sql.DateXX
    java.lang.IntegerXX描述从纪元开始经过的天数
    intX(X)描述从纪元开始已经过的天数。类型为非空null时才会输出

    3.5.2. TIME

    无时区的时间数据类型,由时:分:秒[.小数]组成,精度可达纳秒,值范围从00:00:00.00000000023:59:59.999999999

    SQL/Java/Scala

    与SQL标准相比,该类型不支持闰秒(23:59:60和23:59:61),因为该类型语义更接近java.time.LocalTime。目前不支持带时区的时间。

    SQL

    TIME
    TIME(p)
    
    • 1
    • 2

    java/scala

    DataTypes.TIME(p);
    
    • 1

    桥接到JVM数据类型

    Java 类型InputOutputOutput
    java.time.LocalTimeXX默认
    java.sql.TimeXX
    java.lang.IntegerXX描述当天经过的毫秒值
    intX(X)描述当天经过的毫秒值
    类型为非空null时才会输出
    java.lang.LongXX描述当天经过的纳秒值
    long(X)描述当天经过的纳秒值
    类型为非空null时才会输出

    该类型可以使用TIME(p)声明,其中p是秒后面小数的位数(精度)。P必须有一个介于0和9之间的值(包括两者)。如果没有指定精度,p等于0。

    3.5.3. TIMESTAMP

    无时区的时间戳数据类型,由年-月-日 时:分:秒[.小数]组成,精度可达纳秒,值范围从0000-01-01 00:00:00.0000000009999-12-31 23:59:59.99999999999

    SQL/Java/Scala

    与SQL标准相比,该类型不支持闰秒(23:59:60和23:59:61),因为该类型语义更接近java.time.LocalDateTime

    不支持从BIGINT (JVM long类型)转化为该类型,也不支持从该类型转换到BIGINT (JVM long类型),因为这种转换需要时区,但是该类型是不受时区限制的。
    如果需要使用到时区,则可以使用TIMESTAMP_LTZ类型。

    SQL

    TIMESTAMP
    TIMESTAMP(p)
    
    TIMESTAMP WITHOUT TIME ZONE
    TIMESTAMP(p) WITHOUT TIME ZONE
    
    • 1
    • 2
    • 3
    • 4
    • 5

    java/scala

    DataTypes.TIMESTAMP(p);
    
    • 1

    桥接到JVM数据类型

    Java 类型InputOutputOutput
    java.time.LocalDateTimeXX默认
    java.sql.TimestampXX
    org.apache.flink.table.data.TimestampDataXX内部数据结构

    该类型可以使用TIMESTAMP(p)声明,其中p是秒后面小数(精度)的位数。P必须是一个介于0和9之间的值(包括两者)。如果没有指定精度,则p等于6。

    TIMESTAMP(p) WITHOUT TIME ZONE也表示该类型。

    3.5.4. TIMESTAMP WITH TIME ZONE

    有时区的时间戳的数据类型,由年-月-日 时:分:秒[.分数]组成,精确度可达纳秒,值范围为0000-01-01 00:00:00.000000000 +14:59
    9999-12-31 23:59:59.999999999 -14:59

    TIMESTAMP_LTZ相比,时区偏移信息物理地存储在每个数据中。它被单独用于每一个计算、可视化以及与外部系统通信。

    SQL

    TIMESTAMP WITH TIME ZONE
    TIMESTAMP(p) WITH TIME ZONE
    
    • 1
    • 2

    java/scala

    DataTypes.TIMESTAMP_WITH_TIME_ZONE(p);
    
    • 1

    桥接到JVM数据类型

    Java 类型InputOutputOutput
    java.time.OffsetDateTimeXX默认
    java.time.ZonedDateTimeX忽略时区ID

    3.5.5. TIMESTAMP_LTZ

    使用本地时区的时间戳数据类型,由年-月-日 时:分:秒[.分数]组成,精度可达纳秒,值范围为0000-01-01 00:00:00.000000000 +14:59
    9999-12-31 23:59:59.999999999 -14:59

    该类型允许根据配置的会话时区解释UTC时间戳来填补自由时区和强制时区时间戳类型之间的空白。

    SQL

    TIMESTAMP_LTZ
    TIMESTAMP_LTZ(p)
    
    TIMESTAMP WITH LOCAL TIME ZONE
    TIMESTAMP(p) WITH LOCAL TIME ZONE
    
    • 1
    • 2
    • 3
    • 4
    • 5

    java/scala

    DataTypes.TIMESTAMP_LTZ(p);
    DataTypes.TIMESTAMP_WITH_LOCAL_TIME_ZONE(p);
    
    • 1
    • 2

    桥接到JVM数据类型

    Java 类型InputOutputOutput
    java.time.InstantXX默认
    java.lang.IntegerXX描述从纪元开始经过的秒数
    intX(X)描述从纪元开始经过的秒数
    类型为非空null时才会输出
    java.lang.LongXX描述从纪元开始经过的毫秒数
    longX(X)描述从纪元开始经过的毫秒数
    类型为非空null时才会输出
    java.sql.TimestampXX描述从纪元开始经过的毫秒数
    org.apache.flink.table.data.TimestampDataXX内部数据结构

    可以使用TIMESTAMP_LTZ(p)声明该类型,其中p是秒后面小数(精度)的位数。P必须是一个介于0和9之间的值(包括两者)。如果没有指定精度,则p等于6。

    TIMESTAMP(p) WITH LOCAL TIME ZONE是该类型的同义词。

    3.5.6. INTERVAL YEAR TO MONTH

    一组年-月间隔类型的数据类型。

    该类型必须参数化为以下解析之一:

    • interval of years
    • interval of years to months
    • interval of months

    年-月的间隔由 +year-momth 组成,取值范围为-9999-11 ~ +9999-11

    比如,50个月的间隔以年到月的间隔格式表示为(使用默认的年精度):+04-02

    SQL

    INTERVAL YEAR
    INTERVAL YEAR(p)
    INTERVAL YEAR(p) TO MONTH
    INTERVAL MONTH
    
    • 1
    • 2
    • 3
    • 4

    java/scala

    DataTypes.INTERVAL(DataTypes.YEAR());
    DataTypes.INTERVAL(DataTypes.YEAR(p));
    DataTypes.INTERVAL(DataTypes.YEAR(p),DataTypes.MONTH());
    DataTypes.INTERVAL(DataTypes.MONTH());
    
    • 1
    • 2
    • 3
    • 4

    桥接到JVM数据类型

    Java 类型InputOutputOutput
    java.time.PeriodXX忽略天的部分,默认
    java.lang.IntegerXX描述经过的月数
    intX(X)描述经过的月数
    类型为非空null时才会输出

    可以使用上面的组合声明类型,其中p是年份的位数(年份精度)。P的值必须在1和4之间(包括两者)。如果没有指定年份精度,则p等于2。

    3.5.7. INTERVAL DAY TO SECOND

    一组日间隔类型的数据类型。

    该类型必须参数化为以下解析之一,精度可达纳秒:

    • interval of days
    • interval of days to hours
    • interval of days to minutes
    • interval of days to seconds
    • interval of hours
    • interval of hours to minutes
    • interval of hours to seconds
    • interval of minutes
    • interval of minutes to seconds
    • interval of seconds

    day-time的间隔由 +天 时:分:秒.小数组成,取值范围为-999999 23:59:59.999999999+999999 23:59:59.999999999
    例如,70秒的间隔以天到秒的间隔格式表示(具有默认精度):+00 00:01:10 000000

    SQL

    INTERVAL DAY
    INTERVAL DAY(p1)
    INTERVAL DAY(p1) TO HOUR
    INTERVAL DAY(p1) TO MINUTE
    INTERVAL DAY(p1) TO SECOND(p2)
    INTERVAL HOUR
    INTERVAL HOUR TO MINUTE
    INTERVAL HOUR TO SECOND(p2)
    INTERVAL MINUTE
    INTERVAL MINUTE TO SECOND(p2)
    INTERVAL SECOND
    INTERVAL SECOND(p2)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    java/scala

    DataTypes.INTERVAL(DataTypes.DAY());
    DataTypes.INTERVAL(DataTypes.DAY(p1));
    DataTypes.INTERVAL(DataTypes.DAY(p1),DataTypes.HOUR());
    DataTypes.INTERVAL(DataTypes.DAY(p1),DataTypes.MINUTE());
    DataTypes.INTERVAL(DataTypes.DAY(p1),DataTypes.SECOND(p2));
    DataTypes.INTERVAL(DataTypes.HOUR());
    DataTypes.INTERVAL(DataTypes.HOUR(),DataTypes.MINUTE());
    DataTypes.INTERVAL(DataTypes.HOUR(),DataTypes.SECOND(p2));
    DataTypes.INTERVAL(DataTypes.MINUTE());
    DataTypes.INTERVAL(DataTypes.MINUTE(),DataTypes.SECOND(p2));
    DataTypes.INTERVAL(DataTypes.SECOND());
    DataTypes.INTERVAL(DataTypes.SECOND(p2));
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    桥接到JVM数据类型

    Java 类型InputOutputOutput
    java.time.DurationXX默认
    java.lang.LongXX描述毫秒值
    longX(X)描述毫秒值
    类型为非空null时才会输出

    可以使用上面的组合声明该类型,其中p1是天数(天数精度),p2是小数秒(小数精度)。P1的值必须在1到6之间(包括1和6)。P2的值必须在0到9之间(包括两者)。
    如果没有指定p1,默认值为2。如果没有指定p2,默认值为6。

    3.6. Constructed结构数据类型

    3.6.1. ARRAY

    具有相同子类型元素的数组。

    与SQL标准相比,不能指定数组的最大基数,而是固定在2,147,483,647。此外,支持任何有效类型作为子类型。

    SQL

    ARRAY<t>
    t ARRAY
    
    • 1
    • 2

    java/scala

    DataTypes.ARRAY(t);
    
    • 1

    桥接到JVM数据类型

    Java 类型InputOutputOutput
    t[](X)(X)由子类型决定,默认
    java.util.List XX
    java.util.List 的子类X
    org.apache.flink.table.data.ArrayDataXX内部数据结构

    该类型可以使用ARRAY声明,其中t是所包含元素的数据类型。

    t ARRAY是接近SQL标准的同义词。例如,INT ARRAY等价于ARRAY

    3.6.2. MAP

    关联数组的数据类型,将键(包括NULL)映射到值(包括NULL)。map不能包含重复的键;每个键最多只能映射到一个值。

    元素类型没有限制,需要用户确保数据key的唯一性。

    map类型是对SQL标准的扩展。

    SQL

    MAP<kt, vt>
    
    • 1

    java/scala

    DataTypes.MAP(kt,vt);
    
    • 1

    其中的ktvt都是DataType类型。

    桥接到JVM数据类型

    Java 类型InputOutputOutput
    java.util.MapXX默认
    java.util.MapX
    org.apache.flink.table.data.MapDataXX内部数据类型

    该类型可以使用MAP声明,其中kt是key元素的数据类型,vt是value元素的数据类型。

    3.6.3. MULTISET

    multiset(=bag)数据类型。与map不同,它允许集合中的每个元素存在多个实例。每个唯一的值(包括NULL)可以保存多个。

    元素类型没有限制,需要用户确保唯一性。

    SQL

    MULTISET<t>
    t MULTISET
    
    • 1
    • 2

    java/scala

    DataTypes.MULTISET(t);
    
    • 1

    桥接到JVM数据类型

    Java 类型InputOutputOutput
    java.util.MapXX默认,给每个值分配其对应个数
    java.util.Map子类X
    org.apache.flink.table.data.MapDataXX内部数据类型

    该类型可以使用MULTISET声明,其中t是所包含元素的数据类型。

    MULTISET是接近SQL标准的同义词。例如,INT MULTISET等价于MULTISET

    3.6.4. ROW

    字段序列的数据类型。

    字段由字段名、字段类型和可选描述组成。表中数据最特殊的类型就是 row 类型,每列中 row 类型字段中的所有属性位置都和列中的位置一一对应。

    与SQL标准相比,可选的字段描述简化了复杂结构的处理。

    行类型类似于其他非标准兼容框架中的STRUCT类型。

    SQL

    ROW<n0 t0, n1 t1, ...>
    ROW<n0 t0 'd0', n1 t1 'd1', ...>
    
    ROW(n0 t0, n1 t1, ...)
    ROW(n0 t0 'd0', n1 t1 'd1', ...)
    
    • 1
    • 2
    • 3
    • 4
    • 5

    java/scala

    DataTypes.ROW(DataTypes.FIELD(n0,t0),DataTypes.FIELD(n1,t1),...);
            DataTypes.ROW(DataTypes.FIELD(n0,t0,d0),DataTypes.FIELD(n1,t1,d1),...);
    
    • 1
    • 2

    n0为字段名称,t0为字段类型,d0为字段描述。

    桥接到JVM数据类型

    Java 类型InputOutputOutput
    org.apache.flink.types.RowXX默认
    org.apache.flink.table.data.RowDataXX内部数据结构

    可以使用ROW声明该类型,其中n是字段的唯一名称,t是字段的逻辑类型,d是字段的描述。

    ROW(…)是接近SQL标准的同义词。例如,ROW(myField INT, myOtherField BOOLEAN)等价于ROW

    3.7. 用户自定义数据类型

    目前还不完全支持用户自定义的数据类型。它们目前(从Flink 1.11开始)只在参数和函数返回类型中作为未注册的结构类型。

    结构化类型类似于面向对象编程语言中的对象。它包含零个、一个或多个属性。每个属性由名称和类型组成。

    有两种结构化类型:

    • 存储在catalog中并由catalog标识符标识的类型(如cat.db.MyType)。这些等同于结构化类型的SQL标准定义。
    • 匿名定义、未注册的类型(通常通过反射提取),由其实现类(如com.myorg.model.MyType)标识。这些类型在以编程方式定义表程序中很有用。它们允许重用现有的JVM类,而无需再次手动定义数据类型的模式。

    注册的结构化类型

    目前还不支持注册结构化类型。因此,它们不能存储在catalog中,也不能在CREATE TABLE DDL中引用。

    未注册的结构化类型

    可以使用自动反射提取从常规pojo(普通Java对象)创建未注册的结构化类型。

    结构化类型的实现类必须满足以下要求:

    • 类必须是全局可访问的,这意味着它必须声明为public、static,而不是abstract
    • 类必须提供一个零参数的默认构造函数或一个赋值所有字段的完整参数的构造函数。
    • 类的所有字段必须可以通过public声明或遵循公共编码风格的getter(如getField(), isField(), field())方法读取。
    • 类的所有字段必须由public声明、有完整参数的构造函数或遵循公共编码风格的setter(如setField(…)、field(…))方法写入。
    • 所有字段必须可以通过隐式地反射提取或使用@DataTypeHint注释显式地映射到数据类型。
    • 声明为statictransient的字段将被忽略。

    反射提取支持字段的任意嵌套,只要字段类型不传递性地引用自身。

    声明的字段类行(例如public int age)必须在受支持的JVM桥接类列表中,例如int 为:java.lang.Integerint

    对于某些类,需要一个注释来将类映射到具体的数据类型(例如@DataTypeHint("DECIMAL(10,2)")来为java.math.BigDecimal指定固定的精度和比例)。

    JAVA

    class User {
        // 自动抽取数据类型
        public int age;
        public String name;
        //通过注解丰富其精度信息
        public @DataTypeHint("DECIMAL(10, 2)")
        BigDecimal totalBalance;
        //强制使用RAW类型丰富提取
        public @DataTypeHint("RAW")
        Class<?> modelClass;
    }
    DataTypes.of(User.class);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    scala

    case class User(
    
        // 自动抽取数据类型
        age: Int,
        name: String,
    
        //通过注解丰富其精度信息
        @DataTypeHint("DECIMAL(10, 2)") totalBalance: java.math.BigDecimal,
    
        //强制使用RAW类型丰富提取
        @DataTypeHint("RAW") modelClass: Class[_]
    )
    
    DataTypes.of(classOf[User])
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    桥接到JVM数据类型

    Java 类型InputOutputOutput
    classXX输入:该类或其子类。输出:子类。
    默认
    org.apache.flink.types.RowXX代表row类型的结构体
    org.apache.flink.table.data.RowDataXX内部数据类型

    3.8. 其他数据类型

    3.8.1. BOOLEAN

    布尔数据类型,值为:TRUEFALSEUNKNOWN

    SQL

    BOOLEAN
    
    • 1

    java/scala

    DataTypes.BOOLEAN();
    
    • 1

    桥接到JVM数据类型

    Java 类型InputOutputOutput
    java.lang.BooleanXX默认
    booleanX(X)类型为非空null时才会输出

    3.8.2. RAW

    任意序列化类型的数据类型。这种类型是表生态系统中的黑盒,仅在边缘处进行反序列化。

    该类型是对SQL标准的扩展。

    SQL

    RAW('class', 'snapshot')
    
    • 1

    java/scala

    DataTypes.RAW(class,serializer);
    DataTypes.RAW(class);
    
    • 1
    • 2

    桥接到JVM数据类型

    Java 类型InputOutputOutput
    classXX默认。输入:原始类或子类。输出:子类
    byte[]X
    org.apache.flink.table.data.RawValueDataXX内部数据结构

    SQL/Java/Scala

    该类型可以使用RAW('class', 'snapshot')声明,其中class是原始类,snapshot是Base64编码的序列化的TypeSerializerSnapshot
    通常,类型字符串不是直接声明的,而是在持久化类型时生成的。

    在API中,RAW类型可以通过直接提供Class + TypeSerializer或者通过传递Class并让框架从中提取Class + TypeSerializer来声明。

    3.8.3. NULL

    表示非类型NULL值的数据类型。

    NULL类型是对SQL标准的扩展。NULL类型除了null以外没有其他值,因此,它可以被强制转换为任何可为空的类型,类似于JVM语义。

    这种类型有助于在API调用中表示未知类型,这些调用使用NULL字面量,并桥接到JSON或Avro等格式,这些格式也定义了这种类型。

    这种类型在实践中不是很有用,这里只是为了完整性而提到它。

    SQL

    NULL
    
    • 1

    java/scala

    DataTypes.NULL();
    
    • 1

    桥接到JVM数据类型

    Java 类型InputOutputOutput
    java.lang.ObjectXX默认
    任何类(X)任何非原始类型

    4. 数据类型转换CAST

    Flink Table APISQL 可以将定义的输入类型转化为目标类型,不管输入值是什么,有些转化操作都会成功,但是有些转化会在运行时失败,比如无法为目标类型创建一个正确的值。
    举例:通常来说,可以将一个 INT 值转化为 STRING,但是并不是什么时候都可以将 INT 值转化为 STRING

    在计划期间,查询校验器在遇到校验异常时拒绝无效类型对的查询,比如尝试将 TIMESTAMP 转化为 INTERVAL 类型。查询校验器会接受可能在运行时失败的有效类型对,但是要求用户正确的处理运行失败。

    Flink Table API SQL 中,转化可以使用以下两个内建函数之一来执行:

    • CAST:SQL 标准定义的常规转化函数,该函数会在转化不可靠或者是提供的输入无效时造成任务失败。类型推断将会保留输入类型的可空性(NULL)。
    • TRY_CAST:常规转换函数的扩展函数,在转换操作失败时返回 NULL 值,该函数的返回类型一直保持可空性(NULL)。

    比如:

    CAST('42' AS INT) --- 返回 INT NOT NULL 类型的 42
    CAST(NULL AS VARCHAR) --- 返回 VARCHAR 类型的 NULL
    CAST('non-number' AS INT) --- 抛出异常,并且将任务运行失败
    
    TRY_CAST('42' AS INT) --- 返回 INT 类型的 42
    TRY_CAST(NULL AS VARCHAR) --- 返回 VARCHAR 类型的 NULL
    TRY_CAST('non-number' AS INT) --- 返回 INT 类型的 NULL
    COALESCE(TRY_CAST('non-number' AS INT), 0) --- 返回 INT NOT NULL 类型的 0
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    可空性解释:在flink-1.15.x版本之前,如果你在 SQL 中使用了 ifcase when 表达式,在满足条件时,你想让结果为 NULL,此时直接写 NULL ,是无法运行的。
    但在 flink-1.15.x 中,可以使用新版的转化函数,将 NULL 值转化为对应字段的类型,以此来使用 NULL

    下面的表格展示了支持的可转化类型对,“Y”表示支持,“!”表示失败,“N”表示还不支持。

    Input\TargetCHAR¹/VARCHAR¹/STRINGBINARY¹/VARBINARY¹/BYTESBOOLEANDECIMALTINYINTSMALLINTINTEGERBIGINTFLOATDOUBLEDATETIMETIMESTAMPTIMESTAMP_LTZINTERVALARRAYMULTISETMAPROWSTRUCTUREDRAW
    CHAR/VARCHAR/STRINGY!!!!!!!!!!!!!NNNNNNN
    BINARY/VARBINARY/BYTESYYNNNNNNNNNNNNNNNNNNN
    BOOLEANYNYYYYYYYYNNNNNNNNNNN
    DECIMALYNNYYYYYYYNNNNNNNNNNN
    TINYINTYNYYYYYYYYNNNNNNNNN
    SMALLINTYNYYYYYYYYNNNNNNNNN
    INTEGERYNYYYYYYYYNNY⁵NNNNNN
    BIGINTYNYYYYYYYYNNY⁶NNNNNN
    FLOATYNNYYYYYYYNNNNNNNNNNN
    DOUBLEYNNYYYYYYYNNNNNNNNNNN
    DATEYNNNNNNNNNYNYYNNNNNNN
    TIMEYNNNNNNNNNNYYYNNNNNNN
    TIMESTAMPYNNNNNNNNNYYYYNNNNNNN
    TIMESTAMP_LTZYNNNNNNNNNYYYYNNNNNNN
    INTERVALYNNNNNY⁵Y⁶NNNNNNYNNNNNN
    ARRAYYNNNNNNNNNNNNNNNNNNN
    MULTISETYNNNNNNNNNNNNNNNNNNN
    MAPYNNNNNNNNNNNNNNNNNNN
    ROWYNNNNNNNNNNNNNNNNNNN
    STRUCTUREDYNNNNNNNNNNNNNNNNNNN
    RAWY!NNNNNNNNNNNNNNNNNNY⁴

    注(下面这些数字对应表中的右上角数字):

    1. 所有转化为固定或可变长度的类型,都会根据类型定义对结果值进行截取或使用空格填充。
    2. 必须使用 TO_TIMESTAMP 和 TO_TIMESTAMP_LTZ ,而不是 CAST/TRY_CAST。
    3. 如果子类型对支持,则支持,如果子类型对不支持,则失败。
    4. 如果 RAW 类和序列化类相等,则支持。
    5. 如果 INTERVAL 在 MONTH TO YEAR 范围内,则支持。
    6. 如果 INTERVAL 在 DAY TO TIME 范围内,则支持。

    另外,不管是使用 CAST 还是 TRY_CAST 函数,转化 NULL 都只会返回 NULL 值。

    4.1. 旧版转化

    指1.15.x之前的版本。

    可以设置 table.exec.legacy-cast-behaviourenabled 来使用 Flink-1.15 之前的转化操作,在 Flink-1.15 中,该设置默认禁用。

    开启该参数,将会导致:

    1. 转化为 CHAR/VARCHAR/BINARY/VARBINARY 类型时,将不会对结果值进行截取或填充。
    2. CAST 永远不会失败,而是返回 NULL ,就像是 TRY_CAST 的行为,但是不会参考正确的类型。
    3. 转化一些值为 CHAR/VARCHAR/STRING 类型时,将会产生稍微不同的结果。

    我们不推荐开启该参数,并且强烈建议新的项目保持禁用该参数,并且使用新的转化行为。该参数将会在下个 flink 版本中移除。

    5. 数据类型提取

    在API中,Flink会尝试使用反射从类信息中自动提取数据类型,以避免重复的手动指定工作。但是,反射式提取数据类型并不总是成功的,因为可能缺少逻辑信息。
    因此,可能需要在类或字段声明附近添加额外的信息,以支持提取逻辑。

    下表列出了可以隐式映射到数据类型而不需要进一步添加额外信息的类。

    如果你想使用Scala类,建议使用装箱类型(例如java.lang.Integer),而不是Scala的原生类。
    Scala的原生类(例如IntDouble)被编译为JVM原生类(例如Int / Double),结果如下表所示,增加NOT NULL语义。

    此外,Scala原生类的泛型(例如java.util.Map[Int, Double])在编译过程中会被擦除,最后结果类似于:java.util.Map[java.lang.Object, java.lang.Object]

    Class数据类型
    java.lang.StringSTRING
    java.lang.BooleanBOOLEAN
    booleanBOOLEAN NOT NULL
    java.lang.ByteTINYINT
    byteTINYINT NOT NULL
    java.lang.ShortSMALLINT
    shortSMALLINT NOT NULL
    java.lang.IntegerINT
    intINT NOT NULL
    java.lang.LongBIGINT
    longBIGINT NOT NULL
    java.lang.FloatFLOAT
    java.lang.FloatFLOAT
    floatFLOAT NOT NULL
    java.lang.DoubleDOUBLE
    doubleDOUBLE NOT NULL
    java.sql.DateDATE
    java.time.LocalDateDATE
    java.sql.TimeTIME(0)
    java.time.LocalTimeTIME(9)
    java.sql.TimestampTIMESTAMP(9)
    java.time.LocalDateTimeTIMESTAMP(9)
    java.time.OffsetDateTimeTIMESTAMP(9) WITH TIME ZONE
    java.time.InstantTIMESTAMP_LTZ(9)
    java.time.DurationINTERVAL SECOND(9)
    java.time.PeriodINTERVAL YEAR(4) TO MONTH
    byte[]BYTES
    T[]ARRAY
    java.util.MapMAP
    structured type T匿名 structured type T

    本章节中提到的其他JVM桥接类需要 @DataTypeHint 注解。

    数据类型提示可以参数化或替换单个函数参数和返回类型、结构化类或结构化类的字段的默认提取逻辑。开发者可以通过声明 @DataTypeHint 注解来选择应该在多大程度上修改默认提取逻辑。

    @DataTypeHint 注解提供了一组可选的提示参数。下面的示例显示了其中一些参数。更多信息可以在注解类的文档中找到。

    java

    import org.apache.flink.table.annotation.DataTypeHint;
    
    class User {
        //将java.lang.Integer类转化为 INT 数据类型
        public @DataTypeHint("INT")
        Object o1;
        // 使用显式转换类定义毫秒精度的TIMESTAMP数据类型
        public @DataTypeHint(value = "TIMESTAMP(3)", bridgedTo = java.sql.Timestamp.class)
        Object o2;
        //强制使用RAW类型来丰富类型提取
        public @DataTypeHint("RAW")
        Class<?> modelClass;
        // 定义所有出现的java.math.BigDecimal(也包括嵌套字段)将被提取为DECIMAL(12, 2)
        public @DataTypeHint(defaultDecimalPrecision = 12, defaultDecimalScale = 2)
        AccountStatement stmt;
        // 定义每当类型不能映射到数据类型时,不要抛出异常,而应始终将其视为RAW类型
        public @DataTypeHint(allowRawGlobally = HintFlag.TRUE)
        ComplexModel model;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    scala

    import org.apache.flink.table.annotation.DataTypeHint
    
    class User {
    
        //将java.lang.Integer类转化为 INT 数据类型
        @DataTypeHint("INT")
        var o: AnyRef
    
        // 使用显式转换类定义毫秒精度的TIMESTAMP数据类型
        @DataTypeHint(value = "TIMESTAMP(3)", bridgedTo = java.sql.Timestamp.class)
        var o: AnyRef
    
        //强制使用RAW类型来丰富类型提取
        @DataTypeHint("RAW")
        var modelClass: Class[_]
    
        // 定义所有出现的java.math.BigDecimal(也包括嵌套字段)将被提取为DECIMAL(12, 2)
        @DataTypeHint(defaultDecimalPrecision = 12, defaultDecimalScale = 2)
        var stmt: AccountStatement
    
        // 定义每当类型不能映射到数据类型时,不要抛出异常,而应始终将其视为RAW类型
        @DataTypeHint(allowRawGlobally = HintFlag.TRUE)
        var model: ComplexModel
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
  • 相关阅读:
    深入掌握 Makefile 与 Make 工具:高效管理自动化编译的核心原理和最佳实践
    硬件测试(一):温循
    第二十三章 STL-常用容器
    JDK1.8新特性介绍+Lambda+函数接口+方法、构造方法和数组引用及Stream流
    【计算机视觉】图像聚类&噪声
    按键精灵打怪学习-窗口绑定技能
    【心电信号】小波阙值心电信号去噪【含Matlab源码 2188期】
    Python读取Excel工作表数据写入CSV、XML、文本
    回溯--字母迷宫
    0000-0002 UVa227 Puzzles UVa232 Crossword Answers UVA1368 DNA Consensus String
  • 原文地址:https://blog.csdn.net/u012443641/article/details/127706734