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

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


The following commit(s) were added to refs/heads/release-3.1 by this push:
     new f476a5b1d [FLINK-35592][cdc] Fix MysqlDebeziumTimeConverter miss 
timezone convert to timestamp (#3380)
f476a5b1d is described below

commit f476a5b1dd99fc63962bc75048c0b12957e53da8
Author: ConradJam <[email protected]>
AuthorDate: Thu Jun 13 22:22:09 2024 +0800

    [FLINK-35592][cdc] Fix MysqlDebeziumTimeConverter miss timezone convert to 
timestamp (#3380)
---
 .../converters/MysqlDebeziumTimeConverter.java     | 112 ++++++++++++---------
 .../MysqlDebeziumTimeConverterITCase.java          |   8 +-
 .../src/test/resources/ddl/date_convert_test.sql   |   3 +-
 3 files changed, 73 insertions(+), 50 deletions(-)

diff --git 
a/flink-cdc-connect/flink-cdc-source-connectors/flink-connector-mysql-cdc/src/main/java/io/debezium/connector/mysql/converters/MysqlDebeziumTimeConverter.java
 
b/flink-cdc-connect/flink-cdc-source-connectors/flink-connector-mysql-cdc/src/main/java/io/debezium/connector/mysql/converters/MysqlDebeziumTimeConverter.java
index 493fd682c..1eb98947d 100644
--- 
a/flink-cdc-connect/flink-cdc-source-connectors/flink-connector-mysql-cdc/src/main/java/io/debezium/connector/mysql/converters/MysqlDebeziumTimeConverter.java
+++ 
b/flink-cdc-connect/flink-cdc-source-connectors/flink-connector-mysql-cdc/src/main/java/io/debezium/connector/mysql/converters/MysqlDebeziumTimeConverter.java
@@ -113,54 +113,73 @@ public class MysqlDebeziumTimeConverter
         registration.register(
                 SchemaBuilder.string().name(schemaName).optional(),
                 value -> {
-                    log.debug(
-                            "find schema need to change dateType, field 
name:{} ,field type:{} ,field value:{} ,field "
-                                    + "default:{}",
-                            field.name(),
-                            columnType,
-                            value == null ? "null" : value,
-                            field.hasDefaultValue() ? field.defaultValue() : 
"null");
-                    if (value == null) {
-                        return convertDateDefaultValue(field);
-                    }
-                    switch (columnType.toUpperCase(Locale.ROOT)) {
-                        case "DATE":
-                            if (value instanceof Integer) {
-                                return this.convertToDate(
-                                        columnType, 
LocalDate.ofEpochDay((Integer) value));
-                            }
-                            return this.convertToDate(columnType, value);
-                        case "TIME":
-                            if (value instanceof Long) {
-                                long l =
-                                        Math.multiplyExact(
-                                                (Long) value, 
TimeUnit.MICROSECONDS.toNanos(1));
-                                return this.convertToTime(columnType, 
LocalTime.ofNanoOfDay(l));
-                            }
-                            return this.convertToTime(columnType, value);
-                        case "DATETIME":
-                            if (value instanceof Long) {
-                                if (getTimePrecision(field) <= 3) {
-                                    return this.convertToTimestamp(
-                                            columnType,
-                                            
Conversions.toInstantFromMillis((Long) value));
-                                }
-                                if (getTimePrecision(field) <= 6) {
-                                    return this.convertToTimestamp(
-                                            columnType,
-                                            
Conversions.toInstantFromMicros((Long) value));
-                                }
-                            }
-                            return this.convertToTimestamp(columnType, value);
-                        case "TIMESTAMP":
-                            return 
this.convertToTimestampWithTimezone(columnType, value);
-                        default:
-                            throw new IllegalArgumentException(
-                                    "Unknown field type  " + 
columnType.toUpperCase(Locale.ROOT));
+                    try {
+                        return convertDateObject(field, value, columnType);
+                    } catch (Exception e) {
+                        printConvertDateErrorClassLogs(field, registration, 
value);
+                        throw new RuntimeException("MysqlDebeziumConverter 
error", e);
                     }
                 });
     }
 
+    private void printConvertDateErrorClassLogs(
+            RelationalColumn field,
+            ConverterRegistration<SchemaBuilder> registration,
+            Object value) {
+        boolean useDefaultValueConvert = (value == null);
+        String fieldName = field.name();
+        String fieldType = field.typeName().toUpperCase();
+        String defaultValue = "null";
+        if (field.hasDefaultValue()) {
+            if (field.defaultValue() != null) {
+                defaultValue = field.defaultValue().toString();
+            }
+        }
+        log.warn(
+                "find schema need to change dateType, field name:||{}|| field 
type:||{}|| is use default "
+                        + "convert:||{}|| field default value:||{}|| field 
charge value fail",
+                fieldName,
+                fieldType,
+                useDefaultValueConvert,
+                defaultValue);
+    }
+
+    private Object convertDateObject(RelationalColumn field, Object value, 
String columnType) {
+        if (value == null) {
+            return convertDateDefaultValue(field);
+        }
+        switch (columnType.toUpperCase(Locale.ROOT)) {
+            case "DATE":
+                if (value instanceof Integer) {
+                    return this.convertToDate(columnType, 
LocalDate.ofEpochDay((Integer) value));
+                }
+                return this.convertToDate(columnType, value);
+            case "TIME":
+                if (value instanceof Long) {
+                    long l = Math.multiplyExact((Long) value, 
TimeUnit.MICROSECONDS.toNanos(1));
+                    return this.convertToTime(columnType, 
LocalTime.ofNanoOfDay(l));
+                }
+                return this.convertToTime(columnType, value);
+            case "DATETIME":
+                if (value instanceof Long) {
+                    if (getTimePrecision(field) <= 3) {
+                        return this.convertToTimestamp(
+                                columnType, 
Conversions.toInstantFromMillis((Long) value));
+                    }
+                    if (getTimePrecision(field) <= 6) {
+                        return this.convertToTimestamp(
+                                columnType, 
Conversions.toInstantFromMicros((Long) value));
+                    }
+                }
+                return this.convertToTimestamp(columnType, value);
+            case "TIMESTAMP":
+                return this.convertToTimestampWithTimezone(columnType, value);
+            default:
+                throw new IllegalArgumentException(
+                        "Unknown field type  " + 
columnType.toUpperCase(Locale.ROOT));
+        }
+    }
+
     private Object convertToTimestampWithTimezone(String columnType, Object 
timestamp) {
         // In snapshot mode, debezium produces a java.sql.Timestamp object for 
the TIMESTAMPTZ type.
         // Conceptually, a timestamp with timezone is an Instant. But 
t.toInstant() actually
@@ -174,11 +193,12 @@ public class MysqlDebeziumTimeConverter
             ZonedDateTime zonedDateTime = value.toInstant().atZone(zoneId);
             return ConvertTimeBceUtil.resolveEra(value, 
zonedDateTime.format(timestampFormatter));
         } else if (timestamp instanceof OffsetDateTime) {
-            OffsetDateTime value = (OffsetDateTime) timestamp;
+            OffsetDateTime value =
+                    ((OffsetDateTime) 
timestamp).toInstant().atZone(zoneId).toOffsetDateTime();
             return ConvertTimeBceUtil.resolveEra(
                     value.toLocalDate(), value.format(timestampFormatter));
         } else if (timestamp instanceof ZonedDateTime) {
-            ZonedDateTime zonedDateTime = (ZonedDateTime) timestamp;
+            ZonedDateTime zonedDateTime = ((ZonedDateTime) 
timestamp).toInstant().atZone(zoneId);
             return ConvertTimeBceUtil.resolveEra(
                     zonedDateTime.toLocalDate(), 
zonedDateTime.format(timestampFormatter));
         } else if (timestamp instanceof Instant) {
diff --git 
a/flink-cdc-connect/flink-cdc-source-connectors/flink-connector-mysql-cdc/src/test/java/org/apache/flink/cdc/connectors/mysql/debezium/converters/MysqlDebeziumTimeConverterITCase.java
 
b/flink-cdc-connect/flink-cdc-source-connectors/flink-connector-mysql-cdc/src/test/java/org/apache/flink/cdc/connectors/mysql/debezium/converters/MysqlDebeziumTimeConverterITCase.java
index d14f31f97..8adb92454 100644
--- 
a/flink-cdc-connect/flink-cdc-source-connectors/flink-connector-mysql-cdc/src/test/java/org/apache/flink/cdc/connectors/mysql/debezium/converters/MysqlDebeziumTimeConverterITCase.java
+++ 
b/flink-cdc-connect/flink-cdc-source-connectors/flink-connector-mysql-cdc/src/test/java/org/apache/flink/cdc/connectors/mysql/debezium/converters/MysqlDebeziumTimeConverterITCase.java
@@ -154,7 +154,7 @@ public class MysqlDebeziumTimeConverterITCase {
 
     private void validTimestampValue(List<String> result) throws 
JsonProcessingException {
         ObjectMapper mapper = new ObjectMapper();
-        String[] timestampValues = new String[] {"14:23:00", "00:00:00", 
"00:00:00"};
+        String[] timestampValues = new String[] {"14:23:00", "00:00:00", 
"00:00:00", "15:04:00"};
         for (String after : result) {
             JsonNode jsonNode = mapper.readTree(after);
             Assert.assertEquals(
@@ -232,7 +232,8 @@ public class MysqlDebeziumTimeConverterITCase {
                 new String[] {
                     "+I[1, 14:23:00, 2023-04-01 14:24:00, 2023-04-01, 
14:25:00]",
                     "+I[3, 00:00:00, null, null, 00:01:20]",
-                    "+I[2, 00:00:00, null, null, 00:00:00]"
+                    "+I[2, 00:00:00, null, null, 00:00:00]",
+                    "+I[4, 15:04:00, null, null, 00:01:10]"
                 };
 
         List<String> expectedSnapshotData = new 
ArrayList<>(Arrays.asList(snapshotForSingleTable));
@@ -283,7 +284,8 @@ public class MysqlDebeziumTimeConverterITCase {
                             + "binlog_format = row\n"
                             + "log_bin = mysql-bin\n"
                             + "server-id = 223344\n"
-                            + "binlog_row_image = FULL\n";
+                            + "binlog_row_image = FULL\n"
+                            + "sql_mode = 
ALLOW_INVALID_DATES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION\n";
             String timezoneConf = "default-time_zone = '" + timezone + "'\n";
             Files.write(
                     cnf,
diff --git 
a/flink-cdc-connect/flink-cdc-source-connectors/flink-connector-mysql-cdc/src/test/resources/ddl/date_convert_test.sql
 
b/flink-cdc-connect/flink-cdc-source-connectors/flink-connector-mysql-cdc/src/test/resources/ddl/date_convert_test.sql
index 262c1ceb1..ed9aadfdc 100644
--- 
a/flink-cdc-connect/flink-cdc-source-connectors/flink-connector-mysql-cdc/src/test/resources/ddl/date_convert_test.sql
+++ 
b/flink-cdc-connect/flink-cdc-source-connectors/flink-connector-mysql-cdc/src/test/resources/ddl/date_convert_test.sql
@@ -33,4 +33,5 @@ INSERT INTO date_convert_test (id,test_timestamp, 
test_datetime, test_date, test
 VALUES
 (1,'2023-04-01 14:23:00', '2023-04-01 14:24:00', '2023-04-01', '14:25:00'),
 (2,'2024-04-23 00:00:00', DEFAULT, NULL ,'00:00:00'),
-(3,'2024-04-23 00:00:00', DEFAULT, NULL ,120);
\ No newline at end of file
+(3,'2024-04-23 00:00:00', DEFAULT, NULL ,120),
+(4,20240612150400, DEFAULT, NULL ,110);
\ No newline at end of file

Reply via email to