Skip to content

Commit

Permalink
fixed core mess with date/time types
Browse files Browse the repository at this point in the history
  • Loading branch information
chernser committed Oct 25, 2024
1 parent 38a5ef5 commit 8472f9a
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import java.math.BigInteger;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.sql.Date;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
Expand Down Expand Up @@ -96,11 +97,22 @@ public <E> E[] asArray(Class<E> clazz) {
E[] array = (E[]) Array.newInstance(ClickHouseChecker.nonNull(clazz, ClickHouseValues.TYPE_CLASS), v.length);
int index = 0;
for (T o : v) {
array[index++] = clazz.cast(o);
array[index++] = castOrConvert(o, clazz);
}
return array;
}

private <E> E castOrConvert(T o, Class<E> clazz) {
if (o instanceof LocalDate && clazz == java.sql.Date.class) {
return (E) Date.valueOf((LocalDate) o);
} else if (o instanceof LocalDateTime && clazz == java.sql.Timestamp.class) {
return (E) java.sql.Timestamp.valueOf((LocalDateTime) o);
} else if (o instanceof LocalTime && clazz == java.sql.Time.class) {
return (E) java.sql.Time.valueOf((LocalTime) o);
}
return clazz.cast(o);
}

@Override
public <K, V> Map<K, V> asMap(Class<K> keyClass, Class<V> valueClass) {
if (keyClass == null || valueClass == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import java.sql.Array;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.Map;

import com.clickhouse.data.ClickHouseChecker;
Expand Down Expand Up @@ -46,24 +47,29 @@ public int getBaseType() throws SQLException {
public Object getArray() throws SQLException {
ensureValid();

return resultSet.getValue(columnIndex).asObject();
return resultSet.getObject(columnIndex);
}

@Override
public Object getArray(Map<String, Class<?>> map) throws SQLException {
return getArray();
ensureValid();

return resultSet.getObject(columnIndex, map);
}

@Override
public Object getArray(long index, int count) throws SQLException {
ensureValid();

throw SqlExceptionUtils.unsupportedError("getArray not implemented");
Object[] arr = (Object[]) getArray();
return Arrays.copyOfRange(arr, (int) index, (int) (index + count));
}

@Override
public Object getArray(long index, int count, Map<String, Class<?>> map) throws SQLException {
return getArray(index, count);
ensureValid();

Object[] arr = (Object[]) getArray(map);
return Arrays.copyOfRange(arr, (int) index, (int) (index + count));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,13 @@
import com.clickhouse.client.ClickHouseConfig;
import com.clickhouse.client.ClickHouseResponse;
import com.clickhouse.data.ClickHouseColumn;
import com.clickhouse.data.ClickHouseDataType;
import com.clickhouse.data.ClickHouseRecord;
import com.clickhouse.data.ClickHouseUtils;
import com.clickhouse.data.ClickHouseValue;
import com.clickhouse.data.value.ClickHouseArrayValue;
import com.clickhouse.data.value.ClickHouseDateTimeValue;
import com.clickhouse.data.value.ClickHouseDateValue;

public class ClickHouseResultSet extends AbstractResultSet {
private ClickHouseRecord currentRow;
Expand Down Expand Up @@ -147,7 +151,7 @@ protected void ensureRead(int columnIndex) throws SQLException {
ensureOpen();

if (currentRow == null) {
throw new SQLException("No data available for reading", SqlExceptionUtils.SQL_STATE_NO_DATA);
throw new SQLException("No data available for reading. Was next() called?", SqlExceptionUtils.SQL_STATE_NO_DATA);
} else if (columnIndex < 1 || columnIndex > columns.size()) {
throw SqlExceptionUtils.clientError(ClickHouseUtils
.format("Column index must between 1 and %d but we got %d", columns.size() + 1, columnIndex));
Expand Down Expand Up @@ -362,7 +366,10 @@ public Date getDate(String columnLabel) throws SQLException {

@Override
public Date getDate(int columnIndex, Calendar cal) throws SQLException {
ClickHouseValue value = getValue(columnIndex);
return getDateFromValue(getValue(columnIndex), cal);
}

private Date getDateFromValue(ClickHouseValue value, Calendar cal ) {
if (value.isNullOrEmpty()) {
return null;
}
Expand Down Expand Up @@ -490,7 +497,11 @@ public Object getObject(int columnIndex, Map<String, Class<?>> map) throws SQLEx

Object value;
if (!wrapObject) {
value = javaType != null ? v.asObject(javaType) : v.asObject();
if (javaType == null) {
value = getJDBCDefault( v, c);
} else {
value = v.asObject(javaType);
}
} else if (c.isArray()) {
value = new ClickHouseArray(this, columnIndex);
} else if (c.isTuple() || c.isNested() || c.isMap()) {
Expand All @@ -502,6 +513,28 @@ public Object getObject(int columnIndex, Map<String, Class<?>> map) throws SQLEx
return value;
}

private Object getJDBCDefault(ClickHouseValue v, ClickHouseColumn c) {
if (v instanceof ClickHouseDateValue) {
return getDateFromValue( v, null);
} else if (v instanceof ClickHouseDateTimeValue) {
return getTimestampFromValue(v, c, null);
} else if (v instanceof ClickHouseArrayValue<?>) {
switch (c.getArrayBaseColumn().getDataType()) {
case Date:
case Date32:
return ((ClickHouseArrayValue)v).asArray(java.sql.Date.class);
case DateTime:
case DateTime32:
case DateTime64:
return ((ClickHouseArrayValue)v).asArray(java.sql.Timestamp.class);
default:
return v.asObject();
}
} else {
return v.asObject();
}
}

@Override
public Object getObject(String columnLabel, Map<String, Class<?>> map) throws SQLException {
return getObject(findColumn(columnLabel), map);
Expand Down Expand Up @@ -636,6 +669,10 @@ public Timestamp getTimestamp(int columnIndex, Calendar cal) throws SQLException
}

ClickHouseColumn column = columns.get(columnIndex - 1);
return getTimestampFromValue(value, column, cal);
}

private Timestamp getTimestampFromValue(ClickHouseValue value, ClickHouseColumn column, Calendar cal) {
TimeZone tz = column.getTimeZone();
LocalDateTime dt = tz == null ? value.asDateTime(column.getScale())
: value.asOffsetDateTime(column.getScale()).toLocalDateTime();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.Date;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
Expand Down Expand Up @@ -457,4 +458,32 @@ public void testDateTimeWithoutTimezone() throws SQLException {
Assert.assertEquals(serverNowTimestamp, tzTimeTimestamp);
}
}


@Test(groups = "integration")
public void testGettingDateTimeColumns() throws SQLException {
final String sql = "SELECT toDate(now()) AS d, array(toDate(now())) AS d_arr, " +
" toDateTime(now()) AS dt, array(toDateTime(now())) AS dt_arr";
try (ClickHouseConnection conn = newConnection(new Properties());
Statement stmt = conn.createStatement()) {
ResultSet rs = stmt.executeQuery(sql);
rs.next();

Assert.assertTrue(rs.getObject("d") instanceof java.sql.Date, "Expected java.sql.Date");
Assert.assertTrue(rs.getObject("dt") instanceof java.sql.Timestamp, "Expected java.sql.Timestamp");
Assert.assertTrue(rs.getObject("d_arr") instanceof java.sql.Date[], "Expected java.sql.Date[]");
Assert.assertTrue(rs.getObject("dt_arr") instanceof java.sql.Timestamp[], "Expected java.sql.Timestamp[]");

Assert.assertNotNull(rs.getTime("d"));
Assert.assertNotNull(rs.getTime("dt"));
Assert.assertTrue(rs.getArray("d_arr").getArray() instanceof java.sql.Date[], "Expected java.sql.Date[]");
Assert.assertTrue(rs.getArray("dt_arr").getArray() instanceof java.sql.Timestamp[], "Expected java.sql.Timestamp[]");


Assert.assertNotNull(rs.getObject("d", LocalDate.class), "Expected LocalDate");
Assert.assertNotNull(rs.getObject("dt", LocalDateTime.class), "Expected LocalDateTime");
Assert.assertNotNull(rs.getObject("d_arr", LocalDate[].class), "Expected LocalDate[]");
Assert.assertNotNull(rs.getObject("dt_arr", LocalDateTime[].class), "Expected LocalDateTime[]");
}
}
}

0 comments on commit 8472f9a

Please sign in to comment.