Class CellValueCodec
RowData field into the bytes of a Bigtable cell, and back.
The encoding is the HBase ecosystem's, and that is normative here. A Bigtable cell is
an uninterpreted byte string, so some convention has to be picked; this connector inherits users
from Bigtable-via-HBase, where the convention is org.apache.hadoop.hbase.util.Bytes as
Flink's own HBase connector applies it in HBaseSerde. Reproducing it — rather than
depending on hbase-common, which drags in Hadoop — is what lets a table written by either
connector be read by the other. The layouts below were read from hbase-common 2.6.6 and
flink-connector-hbase-base 4.0.0-1.19 on 2026-08-10; CellValueCodecTest pins each
one to an exact byte array, so a refactor cannot quietly break the interop the choice was made
for.
Two places where the RowData path and the older Row/java.sql path of
that connector disagree, and this follows the RowData one because that is what a Flink
SQL job writes today: DATE is a four-byte day count, not an eight-byte epoch-millis
value, and TIME is a four-byte millisecond-of-day.
What is normative is the byte layouts, not the error policy: a decimal cell overflowing its
declared precision is a decode failure here, where the HBase connector reads null —
silently aliasing real data onto the null convention below (#1038, ADR-0135).
What a fixed-width decoder does with a value longer than its layout is TrailingBytes'
choice, defaulting to the mirrored contract: Bytes.toLong(byte[]) and its siblings
delegate to their offset-taking overloads, whose only bound is offset + length <=
bytes.length, so they read the leading bytes of a longer array without complaint (verified
against hbase-common 2.6.6 on 2026-08-23, ADR-0136). Bytes.toBoolean is the one
member that checks its length, and the BOOLEAN decoder mirrors that under either choice.
A value shorter than its layout fails under both.
A null is an empty cell for every type but a character string, where an empty cell is a
legitimate value — that column writes the null-string-literal instead.
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic interfaceReads the bytes of a cell as one field of a row.static interfaceReads one field of a row as the bytes of a cell. -
Method Summary
Modifier and TypeMethodDescriptionstatic voidcheckSupported(String column, org.apache.flink.table.types.logical.LogicalType type) Rejects a column whose type has no cell encoding, naming the column.static CellValueCodec.FieldDecoderdecoder(org.apache.flink.table.types.logical.LogicalType type, TrailingBytes trailingBytes) Returns a decoder for a cell that is known to hold a value.static CellValueCodec.FieldEncoderencoder(org.apache.flink.table.types.logical.LogicalType type) Returns an encoder for a field that is known to be present.static booleanisTrailingBytesGoverned(org.apache.flink.table.types.logical.LogicalType type) Whethertype's cell layout is one the trailing-bytes policy governs — the fixed-width numeric, temporal and interval layouts decoded through the exact-width check.static CellValueCodec.FieldDecodernullableDecoder(org.apache.flink.table.types.logical.LogicalType type, byte[] nullStringBytes, TrailingBytes trailingBytes) Returns a decoder that reads a null the waynullableEncoder(LogicalType, byte[])wrote it: an empty cell for every type but a character string, where it is thenull-string-literal— an empty string cell is a value in its own right and decodes as one.static CellValueCodec.FieldEncodernullableEncoder(org.apache.flink.table.types.logical.LogicalType type, byte[] nullStringBytes) Returns an encoder that writes a null as an empty cell, or asnullStringBytesfor a character string.
-
Method Details
-
checkSupported
public static void checkSupported(String column, org.apache.flink.table.types.logical.LogicalType type) Rejects a column whose type has no cell encoding, naming the column.Called while the DDL is parsed rather than left to
encoder(LogicalType), so that an unusable column is reported when the sink is built rather than when a row reaches it. That is when the table is first written to, not when it is created: Flink does not consult a connector while registering a table.- Parameters:
column- the column's name, for the messagetype- the declared type- Throws:
org.apache.flink.table.api.ValidationException- if the type cannot be stored in a cell
-
nullableEncoder
public static CellValueCodec.FieldEncoder nullableEncoder(org.apache.flink.table.types.logical.LogicalType type, byte[] nullStringBytes) Returns an encoder that writes a null as an empty cell, or asnullStringBytesfor a character string.- Parameters:
type- the declared typenullStringBytes- thenull-string-literal, UTF-8 encoded- Returns:
- the encoder
-
encoder
public static CellValueCodec.FieldEncoder encoder(org.apache.flink.table.types.logical.LogicalType type) Returns an encoder for a field that is known to be present.- Parameters:
type- the declared type- Returns:
- the encoder
-
nullableDecoder
public static CellValueCodec.FieldDecoder nullableDecoder(org.apache.flink.table.types.logical.LogicalType type, byte[] nullStringBytes, TrailingBytes trailingBytes) Returns a decoder that reads a null the waynullableEncoder(LogicalType, byte[])wrote it: an empty cell for every type but a character string, where it is thenull-string-literal— an empty string cell is a value in its own right and decodes as one.- Parameters:
type- the declared typenullStringBytes- thenull-string-literal, UTF-8 encodedtrailingBytes- what a fixed-width decode does with bytes past the declared layout- Returns:
- the decoder
-
isTrailingBytesGoverned
public static boolean isTrailingBytesGoverned(org.apache.flink.table.types.logical.LogicalType type) Whethertype's cell layout is one the trailing-bytes policy governs — the fixed-width numeric, temporal and interval layouts decoded through the exact-width check.BOOLEANis outside it (its one-byte rule holds under either policy), and so are the variable-width and self-delimiting layouts, which have no trailing bytes to decide about.- Parameters:
type- the declared type- Returns:
- whether the policy decides this type's overlong decode
-
decoder
public static CellValueCodec.FieldDecoder decoder(org.apache.flink.table.types.logical.LogicalType type, TrailingBytes trailingBytes) Returns a decoder for a cell that is known to hold a value.- Parameters:
type- the declared typetrailingBytes- what a fixed-width decode does with bytes past the declared layout- Returns:
- the decoder
-