DBZ-927 Gracefully handling invalid default values for timestamp fields

This commit is contained in:
Deepak Barr 2018-10-02 18:44:21 +08:00 committed by Gunnar Morling
parent 1f25536e2b
commit 4aaed1fd2b
3 changed files with 38 additions and 6 deletions

View File

@ -14,6 +14,7 @@ Cliff Wheadon
David Chen
David Leibovic
David Szabo
Deepak Barr
Denis Mikhaylov
Dennis Persson
Duncan Sands

View File

@ -33,9 +33,10 @@
@Immutable
public class MySqlDefaultValuePreConverter {
private static final Pattern ALL_ZERO_TIMESTAMP = Pattern.compile("0000-00-00 00:00:00(\\.\\d{1,6})?");
private static final String ALL_ZERO_DATE = "0000-00-00";
private static final Pattern EPOCH_EQUIVALENT_TIMESTAMP = Pattern.compile("(\\d{4}-\\d{2}-00|\\d{4}-00-\\d{2}|0000-\\d{2}-\\d{2}) (00:00:00(\\.\\d{1,6})?)");
private static final Pattern EPOCH_EQUIVALENT_DATE = Pattern.compile("\\d{4}-\\d{2}-00|\\d{4}-00-\\d{2}|0000-\\d{2}-\\d{2}");
private static final String EPOCH_TIMESTAMP = "1970-01-01 00:00:00";
@ -97,7 +98,7 @@ public Object convert(Column column, String value) {
* @return the converted value;
*/
private Object convertToLocalDate(Column column, String value) {
final boolean zero = ALL_ZERO_DATE.equals(value) || "0".equals(value);
final boolean zero = EPOCH_EQUIVALENT_DATE.matcher(value).matches() || "0".equals(value);
if (zero && column.isOptional()) {
return null;
}
@ -117,7 +118,7 @@ private Object convertToLocalDate(Column column, String value) {
* @return the converted value;
*/
private Object convertToLocalDateTime(Column column, String value) {
final boolean matches = ALL_ZERO_TIMESTAMP.matcher(value).matches() || "0".equals(value);
final boolean matches = EPOCH_EQUIVALENT_TIMESTAMP.matcher(value).matches() || "0".equals(value);
if (matches) {
if (column.isOptional()) {
return null;
@ -139,7 +140,7 @@ private Object convertToLocalDateTime(Column column, String value) {
* @return the converted value;
*/
private Object convertToTimestamp(Column column, String value) {
final boolean matches = ALL_ZERO_TIMESTAMP.matcher(value).matches() || "0".equals(value) || EPOCH_TIMESTAMP.equals(value);
final boolean matches = EPOCH_EQUIVALENT_TIMESTAMP.matcher(value).matches() || "0".equals(value) || EPOCH_TIMESTAMP.equals(value);
if (matches) {
if (column.isOptional()) {
return null;

View File

@ -339,7 +339,10 @@ public void parseTimeDefaultValue() {
" I datetime(3) NOT NULL DEFAULT '0000-00-00 00:00:00.000'," +
" J datetime NOT NULL DEFAULT '2018-06-26 12:34:56'," +
" K datetime(3) NOT NULL DEFAULT '2018-06-26 12:34:56.000'," +
" L datetime(2) NOT NULL DEFAULT '2018-06-26 12:34:56.78'" +
" L datetime(2) NOT NULL DEFAULT '2018-06-26 12:34:56.78'," +
" M datetime NOT NULL DEFAULT '2000-01-00 00:00:00'," +
" N datetime NOT NULL DEFAULT '0000-12-01 00:00:00'," +
" O datetime NOT NULL DEFAULT '2000-00-01 00:00:00'" +
");";
parser.parse(sql, tables);
Table table = tables.forTable(new TableId(null, null, "TIME_TABLE"));
@ -355,6 +358,33 @@ public void parseTimeDefaultValue() {
assertThat(table.columnWithName("J").defaultValue()).isEqualTo(Date.from(ZonedDateTime.of(2018, 6, 26, 12, 34, 56, 0, ZoneOffset.UTC).toInstant()));
assertThat(table.columnWithName("K").defaultValue()).isEqualTo(Date.from(ZonedDateTime.of(2018, 6, 26, 12, 34, 56, 0, ZoneOffset.UTC).toInstant()));
assertThat(table.columnWithName("L").defaultValue()).isEqualTo(Date.from(ZonedDateTime.of(2018, 6, 26, 12, 34, 56, 780_000_000, ZoneOffset.UTC).toInstant()));
assertThat(table.columnWithName("M").defaultValue()).isEqualTo((Date.from(Instant.ofEpochMilli(0))));
assertThat(table.columnWithName("N").defaultValue()).isEqualTo((Date.from(Instant.ofEpochMilli(0))));
assertThat(table.columnWithName("O").defaultValue()).isEqualTo((Date.from(Instant.ofEpochMilli(0))));
}
@Test
public void parseDateDefaultValue() {
String sql = "CREATE TABLE DATE_TABLE (" +
" A date NOT NULL DEFAULT '0000-00-00'," +
" B date NOT NULL DEFAULT '2018-00-01'," +
" C date NOT NULL DEFAULT '0000-12-31'," +
" D date NOT NULL DEFAULT '2018-01-00'," +
" E date NOT NULL DEFAULT '9999-09-09'," +
" F date NOT NULL DEFAULT '1111-11-11'," +
" G date NOT NULL DEFAULT '2018-08-31'," +
" H date NOT NULL DEFAULT 0" +
");";
parser.parse(sql, tables);
Table table = tables.forTable(new TableId(null, null, "DATE_TABLE"));
assertThat(table.columnWithName("A").defaultValue()).isEqualTo((Date.from(Instant.ofEpochMilli(0))));
assertThat(table.columnWithName("B").defaultValue()).isEqualTo((Date.from(Instant.ofEpochMilli(0))));
assertThat(table.columnWithName("C").defaultValue()).isEqualTo((Date.from(Instant.ofEpochMilli(0))));
assertThat(table.columnWithName("D").defaultValue()).isEqualTo((Date.from(Instant.ofEpochMilli(0))));
assertThat(table.columnWithName("E").defaultValue()).isEqualTo(Date.from(ZonedDateTime.of(9999, 9, 9, 0, 0, 0, 0, ZoneOffset.UTC).toInstant()));
assertThat(table.columnWithName("F").defaultValue()).isEqualTo(Date.from(ZonedDateTime.of(1111, 11, 11, 0, 0, 0, 0, ZoneOffset.UTC).toInstant()));
assertThat(table.columnWithName("G").defaultValue()).isEqualTo(Date.from(ZonedDateTime.of(2018, 8, 31, 0, 0, 0, 0, ZoneOffset.UTC).toInstant()));
assertThat(table.columnWithName("H").defaultValue()).isEqualTo((Date.from(Instant.ofEpochMilli(0))));
}
@Test