@@ -114,6 +114,18 @@ public class KafkaDynamicTableFactory
114114 .noDefaultValue ()
115115 .withDescription ("Optional semantic when committing." );
116116
117+ private static final ConfigOption <DeserFailureHandler > SCAN_DESER_FAILURE_HANDLER =
118+ ConfigOptions .key ("scan.deser.failure-handler" )
119+ .enumType (DeserFailureHandler .class )
120+ .defaultValue (DeserFailureHandler .NONE )
121+ .withDescription ("asd" );
122+
123+ private static final ConfigOption <String > SCAN_DESER_FAILURE_TOPIC =
124+ ConfigOptions .key ("scan.deser.failure-topic" )
125+ .stringType ()
126+ .noDefaultValue ()
127+ .withDescription ("asd" );
128+
117129 public static final String IDENTIFIER = "kafka" ;
118130
119131 @ Override
@@ -152,6 +164,8 @@ public Set<ConfigOption<?>> optionalOptions() {
152164 options .add (SCAN_BOUNDED_MODE );
153165 options .add (SCAN_BOUNDED_SPECIFIC_OFFSETS );
154166 options .add (SCAN_BOUNDED_TIMESTAMP_MILLIS );
167+ options .add (SCAN_DESER_FAILURE_HANDLER );
168+ options .add (SCAN_DESER_FAILURE_TOPIC );
155169 return options ;
156170 }
157171
@@ -201,8 +215,7 @@ public DynamicTableSource createDynamicTableSource(Context context) {
201215 final Properties properties = getKafkaProperties (context .getCatalogTable ().getOptions ());
202216
203217 // add topic-partition discovery
204- final Duration partitionDiscoveryInterval =
205- tableOptions .get (SCAN_TOPIC_PARTITION_DISCOVERY );
218+ final Duration partitionDiscoveryInterval = tableOptions .get (SCAN_TOPIC_PARTITION_DISCOVERY );
206219 properties .setProperty (
207220 KafkaSourceOptions .PARTITION_DISCOVERY_INTERVAL_MS .key (),
208221 Long .toString (partitionDiscoveryInterval .toMillis ()));
@@ -215,6 +228,8 @@ public DynamicTableSource createDynamicTableSource(Context context) {
215228
216229 final String keyPrefix = tableOptions .getOptional (KEY_FIELDS_PREFIX ).orElse (null );
217230
231+ final DeserFailureHandler deserFailureHandler = tableOptions .get (SCAN_DESER_FAILURE_HANDLER );
232+
218233 return createKafkaTableSource (
219234 physicalDataType ,
220235 keyDecodingFormat .orElse (null ),
@@ -231,14 +246,15 @@ public DynamicTableSource createDynamicTableSource(Context context) {
231246 boundedOptions .boundedMode ,
232247 boundedOptions .specificOffsets ,
233248 boundedOptions .boundedTimestampMillis ,
234- context .getObjectIdentifier ().asSummaryString ());
249+ context .getObjectIdentifier ().asSummaryString (),
250+ deserFailureHandler ,
251+ null );
235252 }
236253
237254 @ Override
238255 public DynamicTableSink createDynamicTableSink (Context context ) {
239256 final TableFactoryHelper helper =
240- FactoryUtil .createTableFactoryHelper (
241- this , autoCompleteSchemaRegistrySubject (context ));
257+ FactoryUtil .createTableFactoryHelper (this , autoCompleteSchemaRegistrySubject (context ));
242258
243259 final Optional <EncodingFormat <SerializationSchema <RowData >>> keyEncodingFormat =
244260 getKeyEncodingFormat (helper );
@@ -291,17 +307,15 @@ public DynamicTableSink createDynamicTableSink(Context context) {
291307 private static Optional <DecodingFormat <DeserializationSchema <RowData >>> getKeyDecodingFormat (
292308 TableFactoryHelper helper ) {
293309 final Optional <DecodingFormat <DeserializationSchema <RowData >>> keyDecodingFormat =
294- helper .discoverOptionalDecodingFormat (
295- DeserializationFormatFactory .class , KEY_FORMAT );
310+ helper .discoverOptionalDecodingFormat (DeserializationFormatFactory .class , KEY_FORMAT );
296311 keyDecodingFormat .ifPresent (
297312 format -> {
298313 if (!format .getChangelogMode ().containsOnly (RowKind .INSERT )) {
299314 throw new ValidationException (
300315 String .format (
301316 "A key format should only deal with INSERT-only records. "
302317 + "But %s has a changelog mode of %s." ,
303- helper .getOptions ().get (KEY_FORMAT ),
304- format .getChangelogMode ()));
318+ helper .getOptions ().get (KEY_FORMAT ), format .getChangelogMode ()));
305319 }
306320 });
307321 return keyDecodingFormat ;
@@ -318,45 +332,37 @@ private static Optional<EncodingFormat<SerializationSchema<RowData>>> getKeyEnco
318332 String .format (
319333 "A key format should only deal with INSERT-only records. "
320334 + "But %s has a changelog mode of %s." ,
321- helper .getOptions ().get (KEY_FORMAT ),
322- format .getChangelogMode ()));
335+ helper .getOptions ().get (KEY_FORMAT ), format .getChangelogMode ()));
323336 }
324337 });
325338 return keyEncodingFormat ;
326339 }
327340
328341 private static DecodingFormat <DeserializationSchema <RowData >> getValueDecodingFormat (
329342 TableFactoryHelper helper ) {
330- return helper . discoverOptionalDecodingFormat (
331- DeserializationFormatFactory .class , FactoryUtil .FORMAT )
343+ return helper
344+ . discoverOptionalDecodingFormat ( DeserializationFormatFactory .class , FactoryUtil .FORMAT )
332345 .orElseGet (
333- () ->
334- helper .discoverDecodingFormat (
335- DeserializationFormatFactory .class , VALUE_FORMAT ));
346+ () -> helper .discoverDecodingFormat (DeserializationFormatFactory .class , VALUE_FORMAT ));
336347 }
337348
338349 private static EncodingFormat <SerializationSchema <RowData >> getValueEncodingFormat (
339350 TableFactoryHelper helper ) {
340- return helper . discoverOptionalEncodingFormat (
341- SerializationFormatFactory .class , FactoryUtil .FORMAT )
351+ return helper
352+ . discoverOptionalEncodingFormat ( SerializationFormatFactory .class , FactoryUtil .FORMAT )
342353 .orElseGet (
343- () ->
344- helper .discoverEncodingFormat (
345- SerializationFormatFactory .class , VALUE_FORMAT ));
354+ () -> helper .discoverEncodingFormat (SerializationFormatFactory .class , VALUE_FORMAT ));
346355 }
347356
348357 private static void validatePKConstraints (
349358 ObjectIdentifier tableName ,
350359 int [] primaryKeyIndexes ,
351360 Map <String , String > options ,
352361 Format format ) {
353- if (primaryKeyIndexes .length > 0
354- && format .getChangelogMode ().containsOnly (RowKind .INSERT )) {
362+ if (primaryKeyIndexes .length > 0 && format .getChangelogMode ().containsOnly (RowKind .INSERT )) {
355363 Configuration configuration = Configuration .fromMap (options );
356364 String formatName =
357- configuration
358- .getOptional (FactoryUtil .FORMAT )
359- .orElse (configuration .get (VALUE_FORMAT ));
365+ configuration .getOptional (FactoryUtil .FORMAT ).orElse (configuration .get (VALUE_FORMAT ));
360366 throw new ValidationException (
361367 String .format (
362368 "The Kafka table '%s' with '%s' format doesn't support defining PRIMARY KEY constraint"
@@ -395,7 +401,9 @@ protected KafkaDynamicSource createKafkaTableSource(
395401 BoundedMode boundedMode ,
396402 Map <KafkaTopicPartition , Long > specificEndOffsets ,
397403 long endTimestampMillis ,
398- String tableIdentifier ) {
404+ String tableIdentifier ,
405+ DeserFailureHandler deserFailureHandler ,
406+ @ Nullable Object deserFailureTarget ) {
399407 return new KafkaDynamicSource (
400408 physicalDataType ,
401409 keyDecodingFormat ,
@@ -413,7 +421,9 @@ protected KafkaDynamicSource createKafkaTableSource(
413421 specificEndOffsets ,
414422 endTimestampMillis ,
415423 false ,
416- tableIdentifier );
424+ tableIdentifier ,
425+ deserFailureHandler ,
426+ deserFailureTarget );
417427 }
418428
419429 protected KafkaDynamicSink createKafkaTableSink (
0 commit comments