This is an automated email from the ASF dual-hosted git repository.

lvyanquan pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/flink-cdc.git


The following commit(s) were added to refs/heads/master by this push:
     new f830a6877 [FLINK-41317][pipeline-connector/kafka] Fix NPE when 
serializing REPLACE events without before image (#4610)
f830a6877 is described below

commit f830a687715fff53a6e3501c23904bdc227bdd32
Author: κΉ€λ™ν™˜ <[email protected]>
AuthorDate: Wed Nov 4 10:34:55 2026 +0900

    [FLINK-41317][pipeline-connector/kafka] Fix NPE when serializing REPLACE 
events without before image (#4610)
---
 .../json/canal/CanalJsonSerializationSchema.java    | 18 +++++++++++++++++-
 .../debezium/DebeziumJsonSerializationSchema.java   | 21 ++++++++++++++++++++-
 .../canal/CanalJsonSerializationSchemaTest.java     | 14 ++++++++++++++
 .../DebeziumJsonSerializationSchemaTest.java        | 14 ++++++++++++++
 4 files changed, 65 insertions(+), 2 deletions(-)

diff --git 
a/flink-cdc-connect/flink-cdc-pipeline-connectors/flink-cdc-pipeline-connector-kafka/src/main/java/org/apache/flink/cdc/connectors/kafka/json/canal/CanalJsonSerializationSchema.java
 
b/flink-cdc-connect/flink-cdc-pipeline-connectors/flink-cdc-pipeline-connector-kafka/src/main/java/org/apache/flink/cdc/connectors/kafka/json/canal/CanalJsonSerializationSchema.java
index a9a0209a6..d39206402 100644
--- 
a/flink-cdc-connect/flink-cdc-pipeline-connectors/flink-cdc-pipeline-connector-kafka/src/main/java/org/apache/flink/cdc/connectors/kafka/json/canal/CanalJsonSerializationSchema.java
+++ 
b/flink-cdc-connect/flink-cdc-pipeline-connectors/flink-cdc-pipeline-connector-kafka/src/main/java/org/apache/flink/cdc/connectors/kafka/json/canal/CanalJsonSerializationSchema.java
@@ -187,7 +187,6 @@ public class CanalJsonSerializationSchema implements 
SerializationSchema<Event>
                             .getSerializationSchema()
                             .serialize(reuseGenericRowData);
                 case UPDATE:
-                case REPLACE:
                     reuseGenericRowData.setField(
                             0,
                             new GenericArrayData(
@@ -211,6 +210,23 @@ public class CanalJsonSerializationSchema implements 
SerializationSchema<Event>
                             .get(dataChangeEvent.tableId())
                             .getSerializationSchema()
                             .serialize(reuseGenericRowData);
+                case REPLACE:
+                    // REPLACE events carry only the after image, so "old" is 
written as null.
+                    reuseGenericRowData.setField(0, null);
+                    reuseGenericRowData.setField(
+                            1,
+                            new GenericArrayData(
+                                    new RowData[] {
+                                        jsonSerializers
+                                                .get(dataChangeEvent.tableId())
+                                                .getRowDataFromRecordData(
+                                                        
dataChangeEvent.after(), false)
+                                    }));
+                    reuseGenericRowData.setField(2, OP_UPDATE);
+                    return jsonSerializers
+                            .get(dataChangeEvent.tableId())
+                            .getSerializationSchema()
+                            .serialize(reuseGenericRowData);
                 default:
                     throw new UnsupportedOperationException(
                             format(
diff --git 
a/flink-cdc-connect/flink-cdc-pipeline-connectors/flink-cdc-pipeline-connector-kafka/src/main/java/org/apache/flink/cdc/connectors/kafka/json/debezium/DebeziumJsonSerializationSchema.java
 
b/flink-cdc-connect/flink-cdc-pipeline-connectors/flink-cdc-pipeline-connector-kafka/src/main/java/org/apache/flink/cdc/connectors/kafka/json/debezium/DebeziumJsonSerializationSchema.java
index cbda93dfd..10275333b 100644
--- 
a/flink-cdc-connect/flink-cdc-pipeline-connectors/flink-cdc-pipeline-connector-kafka/src/main/java/org/apache/flink/cdc/connectors/kafka/json/debezium/DebeziumJsonSerializationSchema.java
+++ 
b/flink-cdc-connect/flink-cdc-pipeline-connectors/flink-cdc-pipeline-connector-kafka/src/main/java/org/apache/flink/cdc/connectors/kafka/json/debezium/DebeziumJsonSerializationSchema.java
@@ -208,9 +208,11 @@ public class DebeziumJsonSerializationSchema implements 
SerializationSchema<Even
                     converter = this::convertDeleteEventToRowData;
                     break;
                 case UPDATE:
-                case REPLACE:
                     converter = this::convertUpdateEventToRowData;
                     break;
+                case REPLACE:
+                    converter = this::convertReplaceEventToRowData;
+                    break;
                 default:
                     throw new UnsupportedOperationException(
                             format(
@@ -476,6 +478,23 @@ public class DebeziumJsonSerializationSchema implements 
SerializationSchema<Even
                         
StringData.fromString(dataChangeEvent.tableId().getTableName())));
     }
 
+    private void convertReplaceEventToRowData(
+            DataChangeEvent dataChangeEvent, GenericRowData genericRowData) {
+        // REPLACE events carry only the after image, so "before" is written 
as null.
+        genericRowData.setField(BEFORE.getPosition(), null);
+        genericRowData.setField(
+                AFTER.getPosition(),
+                jsonSerializers
+                        .get(dataChangeEvent.tableId())
+                        .getRowDataFromRecordData(dataChangeEvent.after(), 
false));
+        genericRowData.setField(OPERATION.getPosition(), OP_UPDATE);
+        genericRowData.setField(
+                SOURCE.getPosition(),
+                GenericRowData.of(
+                        
StringData.fromString(dataChangeEvent.tableId().getSchemaName()),
+                        
StringData.fromString(dataChangeEvent.tableId().getTableName())));
+    }
+
     /**
      * Refer to <a
      * 
href="https://debezium.io/documentation/reference/1.9/connectors/mysql.html";>Debezium
diff --git 
a/flink-cdc-connect/flink-cdc-pipeline-connectors/flink-cdc-pipeline-connector-kafka/src/test/java/org/apache/flink/cdc/connectors/kafka/json/canal/CanalJsonSerializationSchemaTest.java
 
b/flink-cdc-connect/flink-cdc-pipeline-connectors/flink-cdc-pipeline-connector-kafka/src/test/java/org/apache/flink/cdc/connectors/kafka/json/canal/CanalJsonSerializationSchemaTest.java
index dc2b71d43..cb78f8fbd 100644
--- 
a/flink-cdc-connect/flink-cdc-pipeline-connectors/flink-cdc-pipeline-connector-kafka/src/test/java/org/apache/flink/cdc/connectors/kafka/json/canal/CanalJsonSerializationSchemaTest.java
+++ 
b/flink-cdc-connect/flink-cdc-pipeline-connectors/flink-cdc-pipeline-connector-kafka/src/test/java/org/apache/flink/cdc/connectors/kafka/json/canal/CanalJsonSerializationSchemaTest.java
@@ -133,6 +133,20 @@ class CanalJsonSerializationSchemaTest {
                         
"{\"old\":[{\"col1\":\"1\",\"col2\":\"1\"}],\"data\":[{\"col1\":\"1\",\"col2\":\"x\"}],\"type\":\"UPDATE\",\"database\":\"default_schema\",\"table\":\"table1\",\"pkNames\":[\"col1\"]}");
         actual = mapper.readTree(serializationSchema.serialize(updateEvent));
         Assertions.assertThat(actual).isEqualTo(expected);
+
+        DataChangeEvent replaceEvent =
+                DataChangeEvent.replaceEvent(
+                        TABLE_1,
+                        generator.generate(
+                                new Object[] {
+                                    BinaryStringData.fromString("1"),
+                                    BinaryStringData.fromString("y")
+                                }));
+        expected =
+                mapper.readTree(
+                        
"{\"old\":null,\"data\":[{\"col1\":\"1\",\"col2\":\"y\"}],\"type\":\"UPDATE\",\"database\":\"default_schema\",\"table\":\"table1\",\"pkNames\":[\"col1\"]}");
+        actual = mapper.readTree(serializationSchema.serialize(replaceEvent));
+        Assertions.assertThat(actual).isEqualTo(expected);
     }
 
     @Test
diff --git 
a/flink-cdc-connect/flink-cdc-pipeline-connectors/flink-cdc-pipeline-connector-kafka/src/test/java/org/apache/flink/cdc/connectors/kafka/json/debezium/DebeziumJsonSerializationSchemaTest.java
 
b/flink-cdc-connect/flink-cdc-pipeline-connectors/flink-cdc-pipeline-connector-kafka/src/test/java/org/apache/flink/cdc/connectors/kafka/json/debezium/DebeziumJsonSerializationSchemaTest.java
index 8ad302560..0be588305 100644
--- 
a/flink-cdc-connect/flink-cdc-pipeline-connectors/flink-cdc-pipeline-connector-kafka/src/test/java/org/apache/flink/cdc/connectors/kafka/json/debezium/DebeziumJsonSerializationSchemaTest.java
+++ 
b/flink-cdc-connect/flink-cdc-pipeline-connectors/flink-cdc-pipeline-connector-kafka/src/test/java/org/apache/flink/cdc/connectors/kafka/json/debezium/DebeziumJsonSerializationSchemaTest.java
@@ -138,6 +138,20 @@ class DebeziumJsonSerializationSchemaTest {
                         
"{\"before\":{\"col1\":\"1\",\"col2\":\"1\"},\"after\":{\"col1\":\"1\",\"col2\":\"x\"},\"op\":\"u\",\"source\":{\"db\":\"default_schema\",\"table\":\"table1\"}}");
         actual = mapper.readTree(serializationSchema.serialize(updateEvent));
         assertThat(actual).isEqualTo(expected);
+
+        DataChangeEvent replaceEvent =
+                DataChangeEvent.replaceEvent(
+                        TABLE_1,
+                        generator.generate(
+                                new Object[] {
+                                    BinaryStringData.fromString("1"),
+                                    BinaryStringData.fromString("y")
+                                }));
+        expected =
+                mapper.readTree(
+                        
"{\"before\":null,\"after\":{\"col1\":\"1\",\"col2\":\"y\"},\"op\":\"u\",\"source\":{\"db\":\"default_schema\",\"table\":\"table1\"}}");
+        actual = mapper.readTree(serializationSchema.serialize(replaceEvent));
+        assertThat(actual).isEqualTo(expected);
     }
 
     @Test

Reply via email to