diff --git a/debezium-connector-binlog/src/main/java/io/debezium/connector/binlog/jdbc/BinlogValueConverters.java b/debezium-connector-binlog/src/main/java/io/debezium/connector/binlog/jdbc/BinlogValueConverters.java index 48d52051d..39f338200 100644 --- a/debezium-connector-binlog/src/main/java/io/debezium/connector/binlog/jdbc/BinlogValueConverters.java +++ b/debezium-connector-binlog/src/main/java/io/debezium/connector/binlog/jdbc/BinlogValueConverters.java @@ -900,8 +900,8 @@ public static LocalDate stringToLocalDate(String dateString, Column column, Tabl final int month = Integer.parseInt(matcher.group(2)); final int day = Integer.parseInt(matcher.group(3)); - if (year == 0 || month == 0 || day == 0) { - LOGGER.warn("Invalid value '{}' stored in column '{}' of table '{}' converted to empty value", + if (month == 0 || day == 0) { + LOGGER.debug("Invalid value '{}' stored in column '{}' of table '{}' converted to empty value", dateString, column.name(), table.id()); return null; } @@ -927,8 +927,8 @@ public static boolean containsZeroValuesInDatePart(String timestampString, Colum final int month = Integer.parseInt(matcher.group(2)); final int day = Integer.parseInt(matcher.group(3)); - if (year == 0 || month == 0 || day == 0) { - LOGGER.warn("Invalid value '{}' stored in column '{}' of table '{}' converted to empty value", + if (month == 0 || day == 0) { + LOGGER.debug("Invalid value '{}' stored in column '{}' of table '{}' converted to empty value", timestampString, column.name(), table.id()); return true; } diff --git a/debezium-connector-binlog/src/test/java/io/debezium/connector/binlog/BinlogValueConvertersTest.java b/debezium-connector-binlog/src/test/java/io/debezium/connector/binlog/BinlogValueConvertersTest.java index a491308c3..38b9313ef 100644 --- a/debezium-connector-binlog/src/test/java/io/debezium/connector/binlog/BinlogValueConvertersTest.java +++ b/debezium-connector-binlog/src/test/java/io/debezium/connector/binlog/BinlogValueConvertersTest.java @@ -6,9 +6,11 @@ package io.debezium.connector.binlog; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.Assert.assertEquals; import java.math.BigDecimal; +import java.sql.Timestamp; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.Month; @@ -265,6 +267,118 @@ public void testZonedDateTimeWithMicrosecondPrecision() { assertEquals("2023-01-11T00:34:10Z", colDConverter.convert(ZonedDateTime.parse("2023-01-11T00:34:10Z"))); } + @Test + public void testInvalidLocalDate() { + LogInterceptor interceptor = new LogInterceptor(BinlogValueConverters.class); + String dateTable = "DATE_TABLE"; + String sql = "CREATE TABLE " + dateTable + " (A DATE NOT NULL);"; + + final BinlogValueConverters converters = getValueConverters( + JdbcValueConverters.DecimalMode.PRECISE, + TemporalPrecisionMode.ADAPTIVE_TIME_MICROSECONDS, + JdbcValueConverters.BigIntUnsignedMode.LONG, + BinaryHandlingMode.BYTES, + x -> x, + EventConvertingFailureHandlingMode.WARN); + + DdlParser parser = getDdlParser(); + Tables tables = new Tables(); + parser.parse(sql, tables); + + Table table = tables.forTable(new TableId(null, null, dateTable)); + Column colA = table.columnWithName("A"); + + LocalDate actual = BinlogValueConverters.stringToLocalDate("0000-00-00", colA, table); + assertThat(actual).isNull(); + + assertThat(interceptor.containsWarnMessage("Invalid value")).isFalse(); + } + + @Test + public void testDateValidYear() { + String dateTable = "DATE_TABLE"; + String sql = "CREATE TABLE " + dateTable + " (A DATE NOT NULL);"; + + final BinlogValueConverters converters = getValueConverters( + JdbcValueConverters.DecimalMode.PRECISE, + TemporalPrecisionMode.ADAPTIVE_TIME_MICROSECONDS, + JdbcValueConverters.BigIntUnsignedMode.LONG, + BinaryHandlingMode.BYTES, + x -> x, + EventConvertingFailureHandlingMode.WARN); + + DdlParser parser = getDdlParser(); + Tables tables = new Tables(); + parser.parse(sql, tables); + + Table table = tables.forTable(new TableId(null, null, dateTable)); + Column colA = table.columnWithName("A"); + + LocalDate actual = BinlogValueConverters.stringToLocalDate("0000-01-01", colA, table); + assertThat(actual).isEqualTo(LocalDate.of(0, 1, 1)); + } + + @Test + public void testInvalidTimestamp() { + LogInterceptor interceptor = new LogInterceptor(BinlogValueConverters.class); + String dateTable = "TIMESTAMP_TABLE"; + String sql = "CREATE TABLE " + dateTable + " (A TIMESTAMP(3) NOT NULL);"; + + final BinlogValueConverters converters = getValueConverters( + JdbcValueConverters.DecimalMode.PRECISE, + TemporalPrecisionMode.ADAPTIVE_TIME_MICROSECONDS, + JdbcValueConverters.BigIntUnsignedMode.LONG, + BinaryHandlingMode.BYTES, + x -> x, + EventConvertingFailureHandlingMode.WARN); + + DdlParser parser = getDdlParser(); + Tables tables = new Tables(); + parser.parse(sql, tables); + + Table table = tables.forTable(new TableId(null, null, dateTable)); + Column colA = table.columnWithName("A"); + + String timestampString = "0000-00-00 00:00:00.000"; + + assertThatThrownBy(() -> { + Timestamp.valueOf(timestampString); + }).isInstanceOf(RuntimeException.class); + + Boolean actual = BinlogValueConverters.containsZeroValuesInDatePart(timestampString, colA, table); + assertThat(actual).isTrue(); + + assertThat(interceptor.containsWarnMessage("Invalid value")).isFalse(); + } + + @Test + public void testTimestampValidYear() { + String dateTable = "TIMESTAMP_TABLE"; + String sql = "CREATE TABLE " + dateTable + " (A TIMESTAMP(3) NOT NULL);"; + + final BinlogValueConverters converters = getValueConverters( + JdbcValueConverters.DecimalMode.PRECISE, + TemporalPrecisionMode.ADAPTIVE_TIME_MICROSECONDS, + JdbcValueConverters.BigIntUnsignedMode.LONG, + BinaryHandlingMode.BYTES, + x -> x, + EventConvertingFailureHandlingMode.WARN); + + DdlParser parser = getDdlParser(); + Tables tables = new Tables(); + parser.parse(sql, tables); + + Table table = tables.forTable(new TableId(null, null, dateTable)); + Column colA = table.columnWithName("A"); + + String timestampString = "0000-01-01 00:00:00.000"; + + assertThat(Timestamp.valueOf(timestampString)).isNotNull(); + + Boolean actual = BinlogValueConverters.containsZeroValuesInDatePart(timestampString, colA, table); + assertThat(actual).isFalse(); + } + protected LocalDate localDateWithYear(int year) { return LocalDate.of(year, Month.APRIL, 4); }