From 9c7f181174ec886c6c07758e08ee2e3314815833 Mon Sep 17 00:00:00 2001 From: Jiri Pechanec Date: Tue, 9 Apr 2019 20:18:04 +0200 Subject: [PATCH] DBZ-1143 Year adjustment configurable; test 19xx years --- .../connector/mysql/MySqlValueConverters.java | 30 ++---------- .../debezium/connector/mysql/MySqlYearIT.java | 48 ++++++++++++++++++- .../src/test/resources/ddl/year_test.sql | 20 +++++++- 3 files changed, 69 insertions(+), 29 deletions(-) diff --git a/debezium-connector-mysql/src/main/java/io/debezium/connector/mysql/MySqlValueConverters.java b/debezium-connector-mysql/src/main/java/io/debezium/connector/mysql/MySqlValueConverters.java index df4926175..ae7d2bee2 100644 --- a/debezium-connector-mysql/src/main/java/io/debezium/connector/mysql/MySqlValueConverters.java +++ b/debezium-connector-mysql/src/main/java/io/debezium/connector/mysql/MySqlValueConverters.java @@ -92,29 +92,6 @@ protected static Temporal adjustTemporal(Temporal temporal) { return temporal; } - /** - * A utility method that adjusts ambiguous 2-digit - * year values of YEAR type using these MySQL-specific rules: - * - * MySQL treats YEAR(4) the same, except that a numeric 00 inserted into YEAR(4) results in 0000 rather than 2000; to - * specify zero for YEAR(4) and have it be interpreted as 2000, specify it as a string '0' or '00'. This should be handled - * by MySQL before Debezium sees the value. - * - * @param year the year value to adjust; may not be null - * @return the possibly adjusted year number; never null - */ - protected static int adjustYear(int year) { - if (0 < year && year <= 69) { - year += 2000; - } else if (70 <= year && year <= 99) { - year += 1900; - } - return year; - } - /** * Create a new instance that always uses UTC for the default time zone when converting values without timezone information * to values that require timezones. @@ -411,18 +388,19 @@ protected Object convertYearToInt(Column column, Field fieldDefn, Object data) { Object mutData = data; if (data instanceof java.time.Year) { // The MySQL binlog always returns a Year object ... - r.deliver(adjustYear(((java.time.Year) data).getValue())); + r.deliver(adjustTemporal(java.time.Year.of(((java.time.Year) data).getValue())).get(ChronoField.YEAR)); } else if (data instanceof java.sql.Date) { // MySQL JDBC driver sometimes returns a Java SQL Date object ... - r.deliver(adjustYear(((java.sql.Date) data).getYear()) + 1900); + // year from java.sql.Date is defined as number of years since 1900 + r.deliver(((java.sql.Date) data).getYear() + 1900); } else if (data instanceof String) { mutData = Integer.valueOf((String) data); } if (mutData instanceof Number) { // MySQL JDBC driver sometimes returns a short ... - r.deliver(adjustYear(((Number) mutData).intValue())); + r.deliver(adjustTemporal(java.time.Year.of(((Number) mutData).intValue())).get(ChronoField.YEAR)); } }); } diff --git a/debezium-connector-mysql/src/test/java/io/debezium/connector/mysql/MySqlYearIT.java b/debezium-connector-mysql/src/test/java/io/debezium/connector/mysql/MySqlYearIT.java index f2ae4c1c1..0b4ba3c18 100644 --- a/debezium-connector-mysql/src/test/java/io/debezium/connector/mysql/MySqlYearIT.java +++ b/debezium-connector-mysql/src/test/java/io/debezium/connector/mysql/MySqlYearIT.java @@ -87,7 +87,16 @@ public void shouldProcessTwoAndForDigitYearsInDatabase() throws SQLException, In " '2018-04-01',\n" + " '18-04-01 12:34:56',\n" + " '0018-04-01 12:34:56',\n" + - " '2018-04-01 12:34:56'\n" + + " '2018-04-01 12:34:56',\n" + + " '78',\n" + + " '0078',\n" + + " '1978',\n" + + " '78-04-01',\n" + + " '0078-04-01',\n" + + " '1978-04-01',\n" + + " '78-04-01 12:34:56',\n" + + " '0078-04-01 12:34:56',\n" + + " '1978-04-01 12:34:56'" + ");"); } @@ -128,7 +137,16 @@ public void shouldProcessTwoAndForDigitYearsInConnector() throws SQLException, I " '2018-04-01',\n" + " '18-04-01 12:34:56',\n" + " '0018-04-01 12:34:56',\n" + - " '2018-04-01 12:34:56'\n" + + " '2018-04-01 12:34:56',\n" + + " '78',\n" + + " '0078',\n" + + " '1978',\n" + + " '78-04-01',\n" + + " '0078-04-01',\n" + + " '1978-04-01',\n" + + " '78-04-01 12:34:56',\n" + + " '0078-04-01 12:34:56',\n" + + " '1978-04-01 12:34:56'" + ");"); } @@ -153,6 +171,19 @@ private void assertChangeRecordByDatabase() throws InterruptedException { Assertions.assertThat(change.getInt64("dt18")).isEqualTo(1_522_586_096_000L); // Assert for 0018 will not work as long is able to handle only 292 years of nanos so we are underflowing Assertions.assertThat(change.getInt64("dt2018")).isEqualTo(1_522_586_096_000L); + + // YEAR does not differentiate between 0078 and 78 + Assertions.assertThat(change.getInt32("y78")).isEqualTo(1978); + Assertions.assertThat(change.getInt32("y0078")).isEqualTo(1978); + Assertions.assertThat(change.getInt32("y1978")).isEqualTo(1978); + + Assertions.assertThat(change.getInt32("d78")).isEqualTo(3012); + Assertions.assertThat(change.getInt32("d0078")).isEqualTo(-690948); + Assertions.assertThat(change.getInt32("d1978")).isEqualTo(3012); + + Assertions.assertThat(change.getInt64("dt78")).isEqualTo(260_282_096_000L); + // Assert for 0018 will not work as long is able to handle only 292 years of nanos so we are underflowing + Assertions.assertThat(change.getInt64("dt1978")).isEqualTo(260_282_096_000L); } private void assertChangeRecordByConnector() throws InterruptedException { @@ -172,5 +203,18 @@ private void assertChangeRecordByConnector() throws InterruptedException { Assertions.assertThat(change.getInt64("dt18")).isEqualTo(1_522_586_096_000L); // Assert for 0018 will not work as long is able to handle only 292 years of nanos so we are underflowing Assertions.assertThat(change.getInt64("dt2018")).isEqualTo(1_522_586_096_000L); + + // YEAR does not differentiate between 0078 and 78 + Assertions.assertThat(change.getInt32("y78")).isEqualTo(1978); + Assertions.assertThat(change.getInt32("y0078")).isEqualTo(1978); + Assertions.assertThat(change.getInt32("y1978")).isEqualTo(1978); + + Assertions.assertThat(change.getInt32("d78")).isEqualTo(3012); + Assertions.assertThat(change.getInt32("d0078")).isEqualTo(3012); + Assertions.assertThat(change.getInt32("d1978")).isEqualTo(3012); + + Assertions.assertThat(change.getInt64("dt78")).isEqualTo(260_282_096_000L); + // Assert for 0018 will not work as long is able to handle only 292 years of nanos so we are underflowing + Assertions.assertThat(change.getInt64("dt1978")).isEqualTo(260_282_096_000L); } } diff --git a/debezium-connector-mysql/src/test/resources/ddl/year_test.sql b/debezium-connector-mysql/src/test/resources/ddl/year_test.sql index c098e1322..ddadd0f97 100644 --- a/debezium-connector-mysql/src/test/resources/ddl/year_test.sql +++ b/debezium-connector-mysql/src/test/resources/ddl/year_test.sql @@ -13,6 +13,15 @@ CREATE TABLE dbz_1143_year_test ( dt18 DATETIME, dt0018 DATETIME, dt2018 DATETIME, + y78 YEAR, + y0078 YEAR, + y1978 YEAR, + d78 DATE, + d0078 DATE, + d1978 DATE, + dt78 DATETIME, + dt0078 DATETIME, + dt1978 DATETIME, PRIMARY KEY (id) ) DEFAULT CHARSET=utf8; @@ -26,5 +35,14 @@ INSERT INTO dbz_1143_year_test VALUES ( '2018-04-01', '18-04-01 12:34:56', '0018-04-01 12:34:56', - '2018-04-01 12:34:56' + '2018-04-01 12:34:56', + '78', + '0078', + '1978', + '78-04-01', + '0078-04-01', + '1978-04-01', + '78-04-01 12:34:56', + '0078-04-01 12:34:56', + '1978-04-01 12:34:56' );