Skip to content
Merged
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 @@ -8,7 +8,6 @@
import java.sql.Timestamp;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

Expand Down Expand Up @@ -103,14 +102,25 @@ public enum ClickHouseDataType {

static {
Map<String, ClickHouseDataType> map = new HashMap<>();
String errorMsg = "[%s] is used by type [%s]";
ClickHouseDataType used = null;
for (ClickHouseDataType t : ClickHouseDataType.values()) {
assert map.put(t.name(), t) == null;
used = map.put(t.name(), t);
if (used != null) {
throw new IllegalStateException(java.lang.String.format(errorMsg, t.name(), used.name()));
}
String nameInUpperCase = t.name().toUpperCase();
if (!nameInUpperCase.equals(t.name())) {
assert map.put(nameInUpperCase, t) == null;
used = map.put(nameInUpperCase, t);
if (used != null) {
throw new IllegalStateException(java.lang.String.format(errorMsg, nameInUpperCase, used.name()));
}
}
for (String alias: t.aliases) {
assert map.put(alias.toUpperCase(), t) == null;
used = map.put(alias.toUpperCase(), t);
if (used != null) {
throw new IllegalStateException(java.lang.String.format(errorMsg, alias, used.name()));
}
}
}
name2type = Collections.unmodifiableMap(map);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -727,7 +727,7 @@ public <T> T getObject(int columnIndex, Class<T> type) throws SQLException {
ClickHouseColumnInfo columnInfo = getColumnInfo(columnIndex);
TimeZone tz = getEffectiveTimeZone(columnInfo);
return columnInfo.isArray()
? (T) getArray(columnIndex)
? (Array.class.isAssignableFrom(type) ? (T) getArray(columnIndex) : (T) getArray(columnIndex).getArray())
: ClickHouseValueParser.getParser(type).parse(getValue(columnIndex), columnInfo, tz);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ protected final LocalDate parseAsLocalDate(String value) {
}

protected final LocalDateTime parseAsLocalDateTime(String value) {
int index = value == null ? -1 : value.indexOf('.');
int index = Objects.requireNonNull(value).indexOf('.');
if (index > 0) {
int endIndex = -1;
for (int i = index + 1, len = value.length(); i < len; i++) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,15 @@ public enum ClickHouseConnectionSettings implements DriverPropertyCreator {
"Whether to use timezone from server on Date parsing in getDate(). " +
"If false, Date returned is a wrapper of a timestamp at start of the day in client timezone. " +
"If true - at start of the day in server or use_timezone timezone."),
CLIENT_NAME("client_name", "", "client_name or http_user_agent show up in system.query_log table, depending on the protocol you're using."),
@Deprecated
USE_NEW_PARSER("use_new_parser", true, "Whether to use JavaCC based SQL parser or not.")
;

private final String key;
private final Object defaultValue;
private final String description;
private final Class clazz;
private final Class<?> clazz;

ClickHouseConnectionSettings(String key, Object defaultValue, String description) {
this.key = key;
Expand All @@ -74,7 +75,7 @@ public Object getDefaultValue() {
return defaultValue;
}

public Class getClazz() {
public Class<?> getClazz() {
return clazz;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ public class ClickHouseProperties {
private Boolean anyJoinDistinctRightTableKeys;
private Boolean sendProgressInHttpHeaders;
private Boolean waitEndOfQuery;
private String clientName;
@Deprecated
private boolean useNewParser;

Expand Down Expand Up @@ -129,6 +130,7 @@ public ClickHouseProperties(Properties info) {
this.useTimeZone = (String)getSetting(info, ClickHouseConnectionSettings.USE_TIME_ZONE);
this.useServerTimeZoneForDates = (Boolean)getSetting(info, ClickHouseConnectionSettings.USE_SERVER_TIME_ZONE_FOR_DATES);
this.useObjectsInArrays = (Boolean)getSetting(info, ClickHouseConnectionSettings.USE_OBJECTS_IN_ARRAYS);
this.clientName = (String)getSetting(info, ClickHouseConnectionSettings.CLIENT_NAME);
this.useNewParser = (Boolean)getSetting(info, ClickHouseConnectionSettings.USE_NEW_PARSER);

this.maxParallelReplicas = getSetting(info, ClickHouseQueryParam.MAX_PARALLEL_REPLICAS);
Expand Down Expand Up @@ -197,6 +199,7 @@ public Properties asProperties() {
ret.put(ClickHouseConnectionSettings.USE_TIME_ZONE.getKey(), String.valueOf(useTimeZone));
ret.put(ClickHouseConnectionSettings.USE_SERVER_TIME_ZONE_FOR_DATES.getKey(), String.valueOf(useServerTimeZoneForDates));
ret.put(ClickHouseConnectionSettings.USE_OBJECTS_IN_ARRAYS.getKey(), String.valueOf(useObjectsInArrays));
ret.put(ClickHouseConnectionSettings.CLIENT_NAME.getKey(), String.valueOf(clientName));
ret.put(ClickHouseConnectionSettings.USE_NEW_PARSER.getKey(), String.valueOf(useNewParser));

ret.put(ClickHouseQueryParam.MAX_PARALLEL_REPLICAS.getKey(), maxParallelReplicas);
Expand Down Expand Up @@ -268,6 +271,7 @@ public ClickHouseProperties(ClickHouseProperties properties) {
setUseTimeZone(properties.useTimeZone);
setUseServerTimeZoneForDates(properties.useServerTimeZoneForDates);
setUseObjectsInArrays(properties.useObjectsInArrays);
setClientName(properties.clientName);
setUseNewParser(properties.useNewParser);
setMaxParallelReplicas(properties.maxParallelReplicas);
setMaxPartitionsPerInsertBlock(properties.maxPartitionsPerInsertBlock);
Expand Down Expand Up @@ -684,6 +688,14 @@ public void setUseObjectsInArrays(boolean useObjectsInArrays) {
this.useObjectsInArrays = useObjectsInArrays;
}

public String getClientName() {
return this.clientName;
}

public void setClientName(String clientName) {
this.clientName = clientName;
}

@Deprecated
public boolean isUseNewParser() {
return useNewParser;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ public ClickHouseHttpClientBuilder(ClickHouseProperties properties) {
}

public CloseableHttpClient buildClient() throws Exception {
return HttpClientBuilder.create()
HttpClientBuilder builder = HttpClientBuilder.create()
.setConnectionManager(getConnectionManager())
.setRetryHandler(getRequestRetryHandler())
.setConnectionReuseStrategy(getConnectionReuseStrategy())
Expand All @@ -76,8 +76,14 @@ public CloseableHttpClient buildClient() throws Exception {
.setDefaultHeaders(getDefaultHeaders())
.setDefaultCredentialsProvider(getDefaultCredentialsProvider())
.disableContentCompression() // gzip is not needed. Use lz4 when compress=1
.disableRedirectHandling()
.build();
.disableRedirectHandling();

String clientName = properties != null ? properties.getClientName() : null;
if (!Utils.isNullOrEmptyString(clientName)) {
builder.setUserAgent(clientName);
}

return builder.build();
}

private HttpRequestRetryHandler getRequestRetryHandler() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package ru.yandex.clickhouse.integration;

import static org.testng.Assert.assertNull;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;

Expand All @@ -24,12 +25,14 @@
import java.util.Calendar;
import java.util.Objects;
import java.util.TimeZone;
import java.util.UUID;

import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

import ru.yandex.clickhouse.ClickHouseArray;
import ru.yandex.clickhouse.ClickHouseConnection;
import ru.yandex.clickhouse.ClickHouseContainerForTest;
import ru.yandex.clickhouse.ClickHouseDataSource;
Expand All @@ -47,7 +50,7 @@ private LocalDate instantToLocalDate(Instant instant, ZoneId zone) {
ZoneRules rules = zone.getRules();
ZoneOffset offset = rules.getOffset(instant);
long localSecond = instant.getEpochSecond() + offset.getTotalSeconds();
long localEpochDay = Math.floorDiv(localSecond, 24 * 3600);
long localEpochDay = Math.floorDiv(localSecond, 24 * 3600L);
return LocalDate.ofEpochDay(localEpochDay);
}

Expand All @@ -56,7 +59,7 @@ private LocalTime instantToLocalTime(Instant instant, ZoneId zone) {
Objects.requireNonNull(zone, "zone");
ZoneOffset offset = zone.getRules().getOffset(instant);
long localSecond = instant.getEpochSecond() + offset.getTotalSeconds();
int secondsADay = 24 * 3600;
long secondsADay = 24 * 3600L;
int secsOfDay = (int) (localSecond - Math.floorDiv(localSecond, secondsADay) * secondsADay);
return LocalTime.ofNanoOfDay(secsOfDay * 1000_000_000L + instant.getNano());
}
Expand Down Expand Up @@ -322,8 +325,9 @@ public void testDateTimeWithTimeZone(String d1TimeZone, String d2TimeZone, Strin
assertEquals(r.getDate("d2"), expectedDate);
assertEquals(r.getObject("d2", Date.class), expectedDate);
}
//expectedDate = new Date(testInstant.atZone(connServerTz.getServerTimeZone().toZoneId())
// .truncatedTo(ChronoUnit.DAYS).toInstant().toEpochMilli());
// expectedDate = new
// Date(testInstant.atZone(connServerTz.getServerTimeZone().toZoneId())
// .truncatedTo(ChronoUnit.DAYS).toInstant().toEpochMilli());
try (Statement s = connServerTz.createStatement(); ResultSet r = s.executeQuery(query);) {
assertTrue(r.next());
assertEquals(r.getDate("d0"), expectedDate);
Expand Down Expand Up @@ -877,6 +881,77 @@ public void testDateWithTimeZone(String testTimeZone) throws Exception {
}
}

@Test
public void testUUID() throws Exception {
try (Statement s = conn.createStatement()) {
s.execute("DROP TABLE IF EXISTS test_uuid");
s.execute(
"CREATE TABLE IF NOT EXISTS test_uuid(u0 UUID, u1 Nullable(UUID), u2 Array(UUID), u3 Array(Nullable(UUID))) ENGINE = Memory");
} catch (ClickHouseException e) {
return;
}

try (Statement s = conn.createStatement()) {
UUID uuid = UUID.randomUUID();
String str = uuid.toString();
s.execute("insert into test_uuid values ('" + str + "', null, ['" + str + "'], [null])");

try (ResultSet rs = s.executeQuery("select * from test_uuid")) {
assertTrue(rs.next());

assertEquals(rs.getString(1), str);
assertEquals(rs.getObject(1), uuid);
assertEquals(rs.getObject(1, UUID.class), uuid);

assertNull(rs.getString(2));
assertNull(rs.getObject(2));
assertNull(rs.getObject(2, UUID.class));

assertEquals(rs.getString(3), "['" + str + "']");
assertEquals(rs.getArray(3).getArray(), new UUID[] { uuid });
assertEquals(rs.getObject(3, ClickHouseArray.class).getArray(), new UUID[] { uuid });
assertEquals(rs.getObject(3, UUID[].class), new UUID[] { uuid });

assertEquals(rs.getString(4), "[NULL]");
assertEquals(rs.getArray(4).getArray(), new UUID[] { null });
assertEquals(rs.getObject(4, ClickHouseArray.class).getArray(), new UUID[] { null });
assertEquals(rs.getObject(4, UUID[].class), new UUID[] { null });
}

s.execute("truncate table test_uuid");
}
}

@Test
public void testDateTime64() throws Exception {
try (Statement s = conn.createStatement()) {
s.execute("DROP TABLE IF EXISTS test_datetime64");
s.execute(
"CREATE TABLE IF NOT EXISTS test_datetime64(d0 DateTime64(3, 'UTC'), d1 Nullable(DateTime64)) ENGINE = Memory");
} catch (ClickHouseException e) {
return;
}

try (Statement s = conn.createStatement()) {
s.execute("insert into test_datetime64 values (1, null)");

try (ResultSet rs = s.executeQuery("select * from test_datetime64")) {
assertTrue(rs.next());
assertEquals(rs.getObject(1), new Timestamp(1L));
assertEquals(rs.getObject(1, Instant.class), Instant.ofEpochMilli(1L));
assertEquals(rs.getObject(1, LocalDate.class), LocalDate.ofEpochDay(0));
assertEquals(rs.getObject(1, LocalDateTime.class),
Instant.ofEpochMilli(1L).atZone(ZoneId.of("UTC")).toLocalDateTime());
assertNull(rs.getObject(2));
assertNull(rs.getObject(2, Instant.class));
assertNull(rs.getObject(2, LocalDate.class));
assertNull(rs.getObject(2, LocalDateTime.class));
}

s.execute("truncate table test_datetime64");
}
}

@Test
public void testDateTimes() throws Exception {
try (Statement s = conn.createStatement()) {
Expand Down