-
Notifications
You must be signed in to change notification settings - Fork 4.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
🎉Source Postgres: 13608, 12026, 14590 - Align regular and CDC integra…
…tion tests and data mappers; improve BCE date handling (#14534) * 13608 & 12026 - align regular and CDC integration tests and data mappers * format code * update int handling * fix build * fix PR remarks * revert changes for money type that are broken by #7338 * bump version * 🐛 Source Postgres: Improve BCE date handling (#15187) * 13608 & 12026 - align regular and CDC integration tests and data mappers * format code * update int handling * borked merge - re-delete deleted methods * enable catalog tests for postgres * fix build * fix PR remarks * revert changes for money type that are broken by #7338 * update BCE handling in JDBC * reuse existing method * handle bce dates * inline methods * fix JDBC BCE year inconsistency * use correct data type in test * format * Update airbyte-integrations/connectors/source-postgres/src/test-integration/java/io/airbyte/integrations/io/airbyte/integration_tests/sources/AbstractPostgresSourceDatatypeTest.java Co-authored-by: Edward Gao <[email protected]> * pmd fix * use class.getname() * fix pmd * format * bump version * handle incremental mode * clean up diff * more comments * unused imports * format * versions+changelog Co-authored-by: Yurii Bidiuk <[email protected]> Co-authored-by: Yurii Bidiuk <[email protected]> * auto-bump connector version [ci skip] Co-authored-by: Edward Gao <[email protected]> Co-authored-by: Octavia Squidington III <[email protected]>
- Loading branch information
1 parent
316502c
commit 708802d
Showing
15 changed files
with
848 additions
and
1,005 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
122 changes: 122 additions & 0 deletions
122
...um-v1-9-2/src/main/java/io/airbyte/integrations/debezium/internals/DateTimeConverter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
/* | ||
* Copyright (c) 2022 Airbyte, Inc., all rights reserved. | ||
*/ | ||
|
||
package io.airbyte.integrations.debezium.internals; | ||
|
||
import static io.airbyte.db.DataTypeUtils.TIMESTAMPTZ_FORMATTER; | ||
import static io.airbyte.db.DataTypeUtils.TIMESTAMP_FORMATTER; | ||
import static io.airbyte.db.DataTypeUtils.TIMETZ_FORMATTER; | ||
import static io.airbyte.db.DataTypeUtils.TIME_FORMATTER; | ||
import static io.airbyte.db.jdbc.AbstractJdbcCompatibleSourceOperations.isBce; | ||
import static io.airbyte.db.jdbc.AbstractJdbcCompatibleSourceOperations.resolveEra; | ||
|
||
import java.sql.Date; | ||
import java.sql.Timestamp; | ||
import java.time.Instant; | ||
import java.time.LocalDate; | ||
import java.time.LocalDateTime; | ||
import java.time.LocalTime; | ||
import java.time.OffsetDateTime; | ||
import java.time.OffsetTime; | ||
import java.time.ZoneOffset; | ||
import java.time.ZonedDateTime; | ||
import java.time.format.DateTimeFormatter; | ||
|
||
public class DateTimeConverter { | ||
|
||
public static final DateTimeFormatter TIME_WITH_TIMEZONE_FORMATTER = DateTimeFormatter.ofPattern( | ||
"HH:mm:ss[.][SSSSSSSSS][SSSSSSS][SSSSSS][SSSSS][SSSS][SSS][SS][S][''][XXX][XX][X]"); | ||
|
||
public static String convertToTimeWithTimezone(Object time) { | ||
OffsetTime timetz = OffsetTime.parse(time.toString(), TIME_WITH_TIMEZONE_FORMATTER); | ||
return timetz.format(TIMETZ_FORMATTER); | ||
} | ||
|
||
public static String convertToTimestampWithTimezone(Object timestamp) { | ||
if (timestamp instanceof Timestamp t) { | ||
// 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 mangles the | ||
// value for ancient dates, because leap years weren't applied consistently in ye olden days. | ||
// Additionally, toInstant() (and toLocalDateTime()) actually lose the era indicator, so we can't | ||
// rely on their getEra() methods. | ||
// So we have special handling for this case, which sidesteps the toInstant conversion. | ||
ZonedDateTime timestamptz = t.toLocalDateTime().atZone(ZoneOffset.UTC); | ||
String value = timestamptz.format(TIMESTAMPTZ_FORMATTER); | ||
return resolveEra(t, value); | ||
} else if (timestamp instanceof OffsetDateTime t) { | ||
// In incremental mode, debezium emits java.time.OffsetDateTime objects. | ||
// java.time classes have a year 0, but the standard AD/BC system does not. For example, | ||
// "0001-01-01 BC" is represented as LocalDate("0000-01-01"). | ||
// We just subtract one year to hack around this difference. | ||
LocalDate localDate = t.toLocalDate(); | ||
if (isBce(localDate)) { | ||
t = t.minusYears(1); | ||
} | ||
return resolveEra(localDate, t.toString()); | ||
} else { | ||
// This case probably isn't strictly necessary, but I'm leaving it just in case there's some weird | ||
// situation that I'm not aware of. | ||
Instant instant = Instant.parse(timestamp.toString()); | ||
OffsetDateTime offsetDateTime = OffsetDateTime.ofInstant(instant, ZoneOffset.UTC); | ||
ZonedDateTime timestamptz = ZonedDateTime.from(offsetDateTime); | ||
LocalDate localDate = timestamptz.toLocalDate(); | ||
String value = timestamptz.format(TIMESTAMPTZ_FORMATTER); | ||
return resolveEra(localDate, value); | ||
} | ||
} | ||
|
||
/** | ||
* See {@link #convertToTimestampWithTimezone(Object)} for explanation of the weird things happening | ||
* here. | ||
*/ | ||
public static String convertToTimestamp(Object timestamp) { | ||
if (timestamp instanceof Timestamp t) { | ||
// Snapshot mode | ||
LocalDateTime localDateTime = t.toLocalDateTime(); | ||
String value = localDateTime.format(TIMESTAMP_FORMATTER); | ||
return resolveEra(t, value); | ||
} else if (timestamp instanceof Instant i) { | ||
// Incremental mode | ||
LocalDate localDate = i.atZone(ZoneOffset.UTC).toLocalDate(); | ||
if (isBce(localDate)) { | ||
// i.minus(1, ChronoUnit.YEARS) would be nice, but it throws an exception because you can't subtract | ||
// YEARS from an Instant | ||
i = i.atZone(ZoneOffset.UTC).minusYears(1).toInstant(); | ||
} | ||
return resolveEra(localDate, i.toString()); | ||
} else { | ||
LocalDateTime localDateTime = LocalDateTime.parse(timestamp.toString()); | ||
final LocalDate date = localDateTime.toLocalDate(); | ||
String value = localDateTime.format(TIMESTAMP_FORMATTER); | ||
return resolveEra(date, value); | ||
} | ||
} | ||
|
||
/** | ||
* See {@link #convertToTimestampWithTimezone(Object)} for explanation of the weird things happening | ||
* here. | ||
*/ | ||
public static Object convertToDate(Object date) { | ||
if (date instanceof Date d) { | ||
// Snapshot mode | ||
LocalDate localDate = ((Date) date).toLocalDate(); | ||
return resolveEra(d, localDate.toString()); | ||
} else if (date instanceof LocalDate d) { | ||
// Incremental mode | ||
if (isBce(d)) { | ||
d = d.minusYears(1); | ||
} | ||
return resolveEra(d, d.toString()); | ||
} else { | ||
LocalDate localDate = LocalDate.parse(date.toString()); | ||
return resolveEra(localDate, localDate.toString()); | ||
} | ||
} | ||
|
||
public static String convertToTime(Object time) { | ||
LocalTime localTime = LocalTime.parse(time.toString()); | ||
return localTime.format(TIME_FORMATTER); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.