Skip to content

Commit 242543b

Browse files
mateczaganyferenc-csaky
authored andcommitted
fix: Read value-format metadata when the value contains the key fields (#436)
Signed-off-by: Mate Czagany <mate@datasqrl.com>
1 parent 8fc6264 commit 242543b

2 files changed

Lines changed: 40 additions & 8 deletions

File tree

‎connectors/kafka-safe-connector/src/main/java/org/apache/flink/streaming/connectors/kafka/table/SafeKafkaDynamicSource.java‎

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -684,12 +684,15 @@ KafkaRecordDeserializationSchema<RowData> createKafkaDeserializationSchema(
684684
final int adjustedPhysicalArity =
685685
DataType.getFieldDataTypes(producedDataType).size() - metadataKeys.size();
686686

687-
// adjust value format projection to include value format's metadata columns at the end
687+
// adjust value format projection to include value format's metadata columns at the end.
688+
// Upstream starts the range at keyProjection.length + valueProjection.length, which counts
689+
// the key fields twice with 'value.fields-include' = 'ALL' and drops the metadata columns.
690+
// TODO: Once FLINK-41255 is released, align this with the upstream fix.
688691
final int[] adjustedValueProjection =
689692
IntStream.concat(
690693
IntStream.of(valueProjection),
691694
IntStream.range(
692-
keyProjection.length + valueProjection.length,
695+
DataType.getFieldDataTypes(physicalDataType).size(),
693696
adjustedPhysicalArity))
694697
.toArray();
695698

‎connectors/kafka-safe-connector/src/test/java/org/apache/flink/streaming/connectors/kafka/table/SafeKafkaDynamicSourceTest.java‎

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -99,14 +99,32 @@ void shouldDropRecordWithoutKeyWhenReadingKeyFieldsFromValueIsDisabled() throws
9999
assertThat(deserialize(schema, "42", "42,Ada")).containsExactly(ROW);
100100
}
101101

102+
@Test
103+
void shouldReadValueFormatMetadataWhenValueContainsKeyFields() throws Exception {
104+
var schema = createSchema(ALL_FIELDS, false, false, List.of("value.m"));
105+
106+
assertThat(deserialize(schema, "42", "42,Ada,m"))
107+
.containsExactly(
108+
GenericRowData.of(
109+
42L, StringData.fromString("Ada"), StringData.fromString("m")));
110+
}
111+
102112
private static KafkaRecordDeserializationSchema<RowData> createSchema(
103113
int[] valueProjection, boolean upsertMode) {
104114
return createSchema(valueProjection, upsertMode, true);
105115
}
106116

107-
@SuppressWarnings("unchecked")
108117
private static KafkaRecordDeserializationSchema<RowData> createSchema(
109118
int[] valueProjection, boolean upsertMode, boolean keyFieldsFromValue) {
119+
return createSchema(valueProjection, upsertMode, keyFieldsFromValue, List.of());
120+
}
121+
122+
@SuppressWarnings("unchecked")
123+
private static KafkaRecordDeserializationSchema<RowData> createSchema(
124+
int[] valueProjection,
125+
boolean upsertMode,
126+
boolean keyFieldsFromValue,
127+
List<String> formatMetadataKeys) {
110128
var source =
111129
new SafeKafkaDynamicSource(
112130
PHYSICAL_TYPE,
@@ -134,17 +152,28 @@ private static KafkaRecordDeserializationSchema<RowData> createSchema(
134152
Optional.empty(),
135153
new SourceWatermarkConfig());
136154

155+
var producedFields = new ArrayList<>(DataType.getFields(PHYSICAL_TYPE));
156+
formatMetadataKeys.forEach(
157+
key -> producedFields.add(DataTypes.FIELD(key, DataTypes.STRING())));
158+
source.applyReadableMetadata(
159+
formatMetadataKeys, DataTypes.ROW(producedFields.toArray(DataTypes.Field[]::new)));
160+
137161
var keyDeserialization =
138162
new CsvDeserializationSchema(
139163
fields -> GenericRowData.of(Long.parseLong(fields[0])));
140164
var valueDeserialization =
141165
new CsvDeserializationSchema(
142166
fields ->
143-
fields.length == 2
144-
? GenericRowData.of(
145-
Long.parseLong(fields[0]),
146-
StringData.fromString(fields[1]))
147-
: GenericRowData.of(StringData.fromString(fields[0])));
167+
switch (fields.length) {
168+
case 1 -> GenericRowData.of(StringData.fromString(fields[0]));
169+
case 2 -> GenericRowData.of(
170+
Long.parseLong(fields[0]),
171+
StringData.fromString(fields[1]));
172+
default -> GenericRowData.of(
173+
Long.parseLong(fields[0]),
174+
StringData.fromString(fields[1]),
175+
StringData.fromString(fields[2]));
176+
});
148177

149178
return source.createKafkaDeserializationSchema(
150179
keyDeserialization, valueDeserialization, mock(TypeInformation.class));

0 commit comments

Comments
 (0)