Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[jdbc] Make ResultSet to return JDBC compliant types for Date/DateTime columns #1886

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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,23 @@ 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,10 +3,13 @@
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;
import com.clickhouse.data.ClickHouseColumn;
import com.clickhouse.data.ClickHouseValue;
import com.clickhouse.data.value.ClickHouseArrayValue;

public class ClickHouseArray implements Array {
private final int columnIndex;
Expand All @@ -24,6 +27,10 @@ protected void ensureValid() throws SQLException {
}
}

/**
* Returns Array base column
* @return
*/
protected ClickHouseColumn getBaseColumn() {
return resultSet.columns.get(columnIndex - 1).getArrayBaseColumn();
}
Expand All @@ -45,25 +52,41 @@ public int getBaseType() throws SQLException {
@Override
public Object getArray() throws SQLException {
ensureValid();

return resultSet.getValue(columnIndex).asObject();
return getArray(null);
}

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

ClickHouseValue v = resultSet.getValue(columnIndex);
Class<?> targetClass = map != null ? map.get(getBaseTypeName()) : null;
switch (getBaseColumn().getDataType()) {
case Date:
case Date32:
return ((ClickHouseArrayValue)v).asArray(targetClass == null ? java.sql.Date.class : targetClass);
case DateTime:
case DateTime32:
case DateTime64:
return ((ClickHouseArrayValue)v).asArray(targetClass == null ? java.sql.Timestamp.class : targetClass);
default:
return targetClass == null ? v.asArray() : v.asArray(targetClass);
}
}

@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,14 @@
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;
import com.clickhouse.data.value.ClickHouseOffsetDateTimeValue;

public class ClickHouseResultSet extends AbstractResultSet {
private ClickHouseRecord currentRow;
Expand Down Expand Up @@ -147,7 +152,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 +367,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 @@ -489,8 +497,12 @@ public Object getObject(int columnIndex, Map<String, Class<?>> map) throws SQLEx
}

Object value;
if (!wrapObject) {
value = javaType != null ? v.asObject(javaType) : v.asObject();
if (!wrapObject && !c.isArray()) {
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,19 +514,38 @@ 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 ClickHouseOffsetDateTimeValue) {
return getTimestampFromValue( v, c, null);
} else if (v instanceof ClickHouseArrayValue<?>) {
throw new RuntimeException("This method does not support array type");
} else {
return v.asObject();
}
}

@Override
public Object getObject(String columnLabel, Map<String, Class<?>> map) throws SQLException {
return getObject(findColumn(columnLabel), map);
}

@Override
public <T> T getObject(int columnIndex, Class<T> type) throws SQLException {
return getValue(columnIndex).asObject(type);
ClickHouseValue v = getValue(columnIndex);
if (v instanceof ClickHouseArrayValue) {
return (T) ((ClickHouseArrayValue)v).asArray(type.componentType());
} else {
return v.asObject(type);
}
}

@Override
public <T> T getObject(String columnLabel, Class<T> type) throws SQLException {
return getValue(findColumn(columnLabel)).asObject(type);
return getObject(findColumn(columnLabel), type);
}

@Override
Expand Down Expand Up @@ -636,6 +667,13 @@ 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) {
if (value.isNullOrEmpty()) {
return null;
}
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 @@ -102,7 +102,8 @@ public void testCreateArray() throws SQLException {
array = conn.createArrayOf("Int8", new Byte[] { -1, 0, 1 });
Assert.assertEquals(array.getArray(), new byte[] { -1, 0, 1 });
array = conn.createArrayOf("UInt8", new Byte[] { -1, 0, 1 });
Assert.assertEquals(array.getArray(), new byte[] { -1, 0, 1 });
Assert.assertEquals(array.getArray(), new UnsignedByte[] { UnsignedByte.valueOf((byte) -1), UnsignedByte.ZERO,
UnsignedByte.ONE});

array = conn.createArrayOf("Nullable(Int8)", new Byte[] { -1, null, 1 });
Assert.assertEquals(array.getArray(), new Byte[] { -1, null, 1 });
Expand Down
Loading
Loading