Maximilian Michels created FLINK-37245:
------------------------------------------
Summary: RowData#createFieldGetter can resurrect null values for
non-null fields
Key: FLINK-37245
URL: https://issues.apache.org/jira/browse/FLINK-37245
Project: Flink
Issue Type: Bug
Components: Table SQL / API, Table SQL / Runtime
Affects Versions: 1.19.1, 1.20.0
Reporter: Maximilian Michels
{{RowData#createFieldGetter}} is the go-to method for creating field getters
for a given field type and position. The method {{FieldGetter#getFieldOrNull}}
suggests that null is returned if the field has been nulled. But that is not
always the case.
When using BinaryRowData with a non-null field, which has been set to null, a
call to {{FieldGetter#getFieldOrNull}} will return a non-null value,
interpreting whatever bytes are backing the field as an actual value instead of
null.
Example:
{noformat}
public static void main(String[] args) {
IntType nullableIntType = new IntType(true);
IntType nonNullableIntType = new IntType(false);
RowDataSerializer rowDataSerializer = new RowDataSerializer(
nullableIntType, nonNullableIntType
);
BinaryRowData binaryRow =
rowDataSerializer.toBinaryRow(GenericRowData.of(null, null));
RowData.FieldGetter fieldGetter1 =
RowData.createFieldGetter(nullableIntType, 0);
RowData.FieldGetter fieldGetter2 =
RowData.createFieldGetter(nonNullableIntType, 1);
System.out.println(fieldGetter1.getFieldOrNull(binaryRow));
System.out.println(fieldGetter2.getFieldOrNull(binaryRow));
}
{noformat}
Output is:
{noformat}
null
0
{noformat}
The expected output would be that the second non-null field also returns null,
or raises a NullPointerException directly. That's not the case because
{{RowData#createFieldGetter}} only checks for null values (via a call to
{{{}Rowdata#isNullAt(pos){}}}) when the type is nullable (see
[https://github.com/apache/flink/blob/b86fdf906c06af8fc2841bca3d98dd3944bb5031/flink-table/flink-table-common/src/main/java/org/apache/flink/table/data/RowData.java#L289]).
It seems fair to always check for null fields, instead of deferring this easy
to forget check to the caller.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)