SQL: Fix issue with getting DATE type in JDBC (#40207)

Previously, calling getDate()/getTime()/getTimestamp() and getObject()
with the corresponding java.sql class on a column of SQL DATE type from
the JDBC result set would throw an Exception.
This commit is contained in:
Marios Trivyzas 2019-03-21 01:14:07 +01:00
parent 5ae43855fc
commit e1eb683c51
3 changed files with 48 additions and 4 deletions

View File

@ -90,6 +90,10 @@ class JdbcResultSet implements ResultSet, JdbcWrapper {
return index.intValue();
}
private EsType columnType(int columnIndex) {
return cursor.columns().get(columnIndex - 1).type;
}
void checkOpen() throws SQLException {
if (isClosed()) {
throw new SQLException("Closed result set");
@ -242,7 +246,7 @@ class JdbcResultSet implements ResultSet, JdbcWrapper {
private Long dateTime(int columnIndex) throws SQLException {
Object val = column(columnIndex);
EsType type = cursor.columns().get(columnIndex - 1).type;
EsType type = columnType(columnIndex);
try {
// TODO: the B6 appendix of the jdbc spec does mention CHAR, VARCHAR, LONGVARCHAR, DATE, TIMESTAMP as supported
// jdbc types that should be handled by getDate and getTime methods. From all of those we support VARCHAR and
@ -282,6 +286,10 @@ class JdbcResultSet implements ResultSet, JdbcWrapper {
@Override
public Time getTime(int columnIndex, Calendar cal) throws SQLException {
EsType type = columnType(columnIndex);
if (type == EsType.DATE) {
return new Time(0L);
}
return TypeConverter.convertTime(dateTime(columnIndex), safeCalendar(cal));
}
@ -336,7 +344,7 @@ class JdbcResultSet implements ResultSet, JdbcWrapper {
return null;
}
EsType columnType = cursor.columns().get(columnIndex - 1).type;
EsType columnType = columnType(columnIndex);
String typeString = type != null ? type.getSimpleName() : columnType.getName();
return TypeConverter.convert(val, columnType, type, typeString);

View File

@ -469,7 +469,7 @@ final class TypeConverter {
}
private static Date asDate(Object val, EsType columnType, String typeString) throws SQLException {
if (columnType == EsType.DATETIME) {
if (columnType == EsType.DATETIME || columnType == EsType.DATE) {
return JdbcDateUtils.asDateTimeField(val, JdbcDateUtils::asDate, Date::new);
}
return failConversion(val, columnType, typeString, Date.class);
@ -479,11 +479,14 @@ final class TypeConverter {
if (columnType == EsType.DATETIME) {
return JdbcDateUtils.asDateTimeField(val, JdbcDateUtils::asTime, Time::new);
}
if (columnType == EsType.DATE) {
return new Time(0L);
}
return failConversion(val, columnType, typeString, Time.class);
}
private static Timestamp asTimestamp(Object val, EsType columnType, String typeString) throws SQLException {
if (columnType == EsType.DATETIME) {
if (columnType == EsType.DATETIME || columnType == EsType.DATE) {
return JdbcDateUtils.asDateTimeField(val, JdbcDateUtils::asTimestamp, Timestamp::new);
}
return failConversion(val, columnType, typeString, Timestamp.class);

View File

@ -1096,6 +1096,39 @@ public class ResultSetTestCase extends JdbcIntegrationTestCase {
});
}
public void testGetDateType() throws Exception {
createIndex("test");
updateMapping("test", builder -> builder.startObject("test_date").field("type", "date").endObject());
// 2018-03-12 17:00:00 UTC
Long timeInMillis = 1520874000123L;
index("test", "1", builder -> builder.field("test_date", timeInMillis));
// UTC +10 hours
String timeZoneId1 = "Etc/GMT-10";
Calendar c = Calendar.getInstance(TimeZone.getTimeZone(timeZoneId1), Locale.ROOT);
doWithQueryAndTimezone("SELECT CAST(test_date AS DATE) as date FROM test", timeZoneId1, results -> {
results.next();
c.setTimeInMillis(timeInMillis);
c.set(HOUR_OF_DAY, 0);
c.set(MINUTE, 0);
c.set(SECOND, 0);
c.set(MILLISECOND, 0);
java.sql.Date expectedDate = new java.sql.Date(c.getTimeInMillis());
assertEquals(expectedDate, results.getDate("date"));
assertEquals(expectedDate, results.getObject("date", java.sql.Date.class));
java.sql.Time expectedTime = new java.sql.Time(0L);
assertEquals(expectedTime, results.getTime("date"));
assertEquals(expectedTime, results.getObject("date", java.sql.Time.class));
java.sql.Timestamp expectedTimestamp = new java.sql.Timestamp(c.getTimeInMillis());
assertEquals(expectedTimestamp, results.getTimestamp("date"));
assertEquals(expectedTimestamp, results.getObject("date", java.sql.Timestamp.class));
});
}
public void testValidGetObjectCalls() throws Exception {
createIndex("test");
updateMappingForNumericValuesTests("test");