Skip to content

Commit 5137f35

Browse files
committed
Merge branch 'main' into new_time_datatypes
2 parents 320a49d + d9fda17 commit 5137f35

File tree

10 files changed

+746
-37
lines changed

10 files changed

+746
-37
lines changed

client-v2/src/main/java/com/clickhouse/client/api/Client.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
import com.clickhouse.client.api.data_formats.RowBinaryFormatReader;
88
import com.clickhouse.client.api.data_formats.RowBinaryWithNamesAndTypesFormatReader;
99
import com.clickhouse.client.api.data_formats.RowBinaryWithNamesFormatReader;
10-
import com.clickhouse.client.api.data_formats.internal.AbstractBinaryFormatReader;
1110
import com.clickhouse.client.api.data_formats.internal.BinaryStreamReader;
1211
import com.clickhouse.client.api.data_formats.internal.MapBackedRecord;
1312
import com.clickhouse.client.api.data_formats.internal.ProcessParser;
@@ -37,7 +36,6 @@
3736
import com.clickhouse.client.api.transport.Endpoint;
3837
import com.clickhouse.client.api.transport.HttpEndpoint;
3938
import com.clickhouse.client.config.ClickHouseClientOption;
40-
import com.clickhouse.config.ClickHouseOption;
4139
import com.clickhouse.data.ClickHouseColumn;
4240
import com.clickhouse.data.ClickHouseDataType;
4341
import com.clickhouse.data.ClickHouseFormat;
@@ -1575,7 +1573,7 @@ public CompletableFuture<QueryResponse> query(String sqlQuery, Map<String, Objec
15751573
Supplier<QueryResponse> responseSupplier;
15761574

15771575
if (queryParams != null) {
1578-
settings.setOption("statement_params", queryParams);
1576+
settings.setOption(HttpAPIClientHelper.KEY_STATEMENT_PARAMS, queryParams);
15791577
}
15801578
final QuerySettings finalSettings = new QuerySettings(buildRequestSettings(settings.getAllSettings()));
15811579
responseSupplier = () -> {
@@ -2027,6 +2025,7 @@ protected int getOperationTimeout() {
20272025
* @return - set of endpoints
20282026
* @deprecated
20292027
*/
2028+
@Deprecated
20302029
public Set<String> getEndpoints() {
20312030
return endpoints.stream().map(Endpoint::getBaseURL).collect(Collectors.toSet());
20322031
}
@@ -2100,4 +2099,5 @@ private Map<String, Object> buildRequestSettings(Map<String, Object> opSettings)
21002099
requestSettings.putAll(opSettings);
21012100
return requestSettings;
21022101
}
2102+
21032103
}

client-v2/src/main/java/com/clickhouse/client/api/DataTypeUtils.java

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,17 @@
11
package com.clickhouse.client.api;
22

3+
import java.time.Instant;
4+
import java.time.ZoneId;
35
import com.clickhouse.client.api.data_formats.internal.BinaryStreamReader;
46

57
import java.time.Instant;
68
import java.time.ZoneId;
79
import java.time.format.DateTimeFormatter;
10+
import java.time.format.DateTimeFormatterBuilder;
11+
import java.time.temporal.ChronoField;
12+
import java.util.Objects;
13+
14+
import com.clickhouse.data.ClickHouseDataType;
815

916
import static com.clickhouse.client.api.data_formats.internal.BinaryStreamReader.BASES;
1017

@@ -25,6 +32,93 @@ public class DataTypeUtils {
2532
*/
2633
public static DateTimeFormatter DATETIME_WITH_NANOS_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.nnnnnnnnn");
2734

35+
private static final DateTimeFormatter INSTANT_FORMATTER = new DateTimeFormatterBuilder()
36+
.appendValue(ChronoField.INSTANT_SECONDS)
37+
.appendFraction(ChronoField.NANO_OF_SECOND, 9, 9, true)
38+
.toFormatter();
39+
40+
/**
41+
* Formats an {@link Instant} object for use in SQL statements or as query
42+
* parameter.
43+
*
44+
* @param instant
45+
* the Java object to format
46+
* @return a suitable String representation of {@code instant}
47+
* @throws NullPointerException
48+
* if {@code instant} is null
49+
*/
50+
public static String formatInstant(Instant instant) {
51+
return formatInstant(instant, null);
52+
}
53+
54+
/**
55+
* Formats an {@link Instant} object for use in SQL statements or as query
56+
* parameter.
57+
*
58+
* This method uses the {@code dataTypeHint} parameter to find the best
59+
* suitable format for the instant.
60+
*
61+
* @param instant
62+
* the Java object to format
63+
* @param dataTypeHint
64+
* the ClickHouse data type {@code instant} should be used for
65+
* @return a suitable String representation of {@code instant}
66+
* @throws NullPointerException
67+
* if {@code instant} is null
68+
*/
69+
public static String formatInstant(Instant instant, ClickHouseDataType dataTypeHint) {
70+
return formatInstant(instant, dataTypeHint, null);
71+
}
72+
73+
/**
74+
* Formats an {@link Instant} object for use in SQL statements or as query
75+
* parameter.
76+
*
77+
* This method uses the {@code dataTypeHint} parameter to find the best
78+
* suitable format for the instant.
79+
*
80+
* For <em>some</em> formatting operations, providing a {@code timeZone} is
81+
* mandatory, e.g. for {@link ClickHouseDataType#Date}.
82+
*
83+
* @param instant
84+
* the Java object to format
85+
* @param dataTypeHint
86+
* the ClickHouse data type {@code object} should be used for
87+
* @param timeZone
88+
* the time zone to be used when formatting the instant for use
89+
* in non-time-zone-based ClickHouse data types
90+
* @return a suitable String representation of {@code object}, or the empty
91+
* String for {@code null} objects
92+
* @throws NullPointerException
93+
* if {@code instant} is null
94+
*/
95+
public static String formatInstant(Instant instant, ClickHouseDataType dataTypeHint,
96+
ZoneId timeZone)
97+
{
98+
Objects.requireNonNull(instant, "Instant required for formatInstant");
99+
if (dataTypeHint == null) {
100+
return formatInstantDefault(instant);
101+
}
102+
switch (dataTypeHint) {
103+
case Date:
104+
case Date32:
105+
Objects.requireNonNull(
106+
timeZone,
107+
"TimeZone required for formatting Instant for '" + dataTypeHint + "' use");
108+
return DATE_FORMATTER.format(
109+
instant.atZone(timeZone).toLocalDate());
110+
case DateTime:
111+
case DateTime32:
112+
return String.valueOf(instant.getEpochSecond());
113+
default:
114+
return formatInstantDefault(instant);
115+
}
116+
}
117+
118+
private static String formatInstantDefault(Instant instant) {
119+
return INSTANT_FORMATTER.format(instant);
120+
}
121+
28122
public static Instant instantFromTime64Integer(int precision, long value) {
29123
int nanoSeconds = 0;
30124
if (precision > 0) {

client-v2/src/main/java/com/clickhouse/client/api/data_formats/RowBinaryFormatSerializer.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
import com.clickhouse.client.api.data_formats.internal.SerializerUtils;
44
import com.clickhouse.data.ClickHouseColumn;
55
import com.clickhouse.data.ClickHouseDataType;
6-
import com.clickhouse.data.ClickHouseFormat;
76
import com.clickhouse.data.format.BinaryStreamUtils;
87

98
import java.io.IOException;
@@ -132,7 +131,7 @@ public void writeFixedString(String value, int len) throws IOException {
132131
}
133132

134133
public void writeDate(ZonedDateTime value) throws IOException {
135-
SerializerUtils.writeDate(out, value, ZoneId.of("UTC"));
134+
SerializerUtils.writeDate(out, value, value.getZone());
136135
}
137136

138137
public void writeDate32(ZonedDateTime value, ZoneId targetTz) throws IOException {

client-v2/src/main/java/com/clickhouse/client/api/data_formats/internal/BinaryStreamReader.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ public <T> T readValue(ClickHouseColumn column, Class<?> typeHint) throws IOExce
104104
if (column.isNullable()) {
105105
int isNull = readByteOrEOF(input);
106106
if (isNull == 1) { // is Null?
107-
return (T) null;
107+
return null;
108108
}
109109
}
110110

@@ -592,7 +592,7 @@ public static byte[] readNBytesLE(InputStream input, byte[] buffer, int offset,
592592

593593
return bytes;
594594
}
595-
595+
596596
/**
597597
* Reads a array into an ArrayValue object.
598598
* @param column - column information
@@ -968,7 +968,7 @@ private ZonedDateTime readDateTime32(TimeZone tz) throws IOException {
968968
*/
969969
public static ZonedDateTime readDateTime32(InputStream input, byte[] buff, TimeZone tz) throws IOException {
970970
long time = readUnsignedIntLE(input, buff);
971-
return LocalDateTime.ofInstant(Instant.ofEpochSecond(Math.max(time, 0L)), tz.toZoneId()).atZone(tz.toZoneId());
971+
return Instant.ofEpochSecond(Math.max(time, 0L)).atZone(tz.toZoneId());
972972
}
973973

974974
/**

client-v2/src/main/java/com/clickhouse/client/api/data_formats/internal/SerializerUtils.java

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,6 @@
1717
import org.objectweb.asm.MethodVisitor;
1818
import org.objectweb.asm.Opcodes;
1919
import org.objectweb.asm.Type;
20-
import org.slf4j.Logger;
21-
import org.slf4j.LoggerFactory;
22-
2320
import java.io.IOException;
2421
import java.io.OutputStream;
2522
import java.lang.reflect.Array;
@@ -29,7 +26,14 @@
2926
import java.net.Inet4Address;
3027
import java.net.Inet6Address;
3128
import java.sql.Timestamp;
32-
import java.time.*;
29+
import java.time.Duration;
30+
import java.time.Instant;
31+
import java.time.LocalDate;
32+
import java.time.LocalDateTime;
33+
import java.time.OffsetDateTime;
34+
import java.time.Period;
35+
import java.time.ZoneId;
36+
import java.time.ZonedDateTime;
3337
import java.util.Arrays;
3438
import java.util.Collections;
3539
import java.util.HashMap;
@@ -54,8 +58,6 @@
5458

5559
public class SerializerUtils {
5660

57-
private static final Logger LOG = LoggerFactory.getLogger(SerializerUtils.class);
58-
5961
public static void serializeData(OutputStream stream, Object value, ClickHouseColumn column) throws IOException {
6062
//Serialize the value to the stream based on the data type
6163
switch (column.getDataType()) {
@@ -1095,6 +1097,9 @@ public static void writeDate(OutputStream output, Object value, ZoneId targetTz)
10951097
} else if (value instanceof ZonedDateTime) {
10961098
ZonedDateTime dt = (ZonedDateTime) value;
10971099
epochDays = (int)dt.withZoneSameInstant(targetTz).toLocalDate().toEpochDay();
1100+
} else if (value instanceof OffsetDateTime) {
1101+
OffsetDateTime dt = (OffsetDateTime) value;
1102+
epochDays = (int) dt.atZoneSameInstant(targetTz).toLocalDate().toEpochDay();
10981103
} else {
10991104
throw new IllegalArgumentException("Cannot convert " + value + " to Long");
11001105
}

client-v2/src/main/java/com/clickhouse/client/api/internal/HttpAPIClientHelper.java

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,10 @@
9898
import java.util.regex.Pattern;
9999

100100
public class HttpAPIClientHelper {
101-
private static final Logger LOG = LoggerFactory.getLogger(Client.class);
101+
102+
public static final String KEY_STATEMENT_PARAMS = "statement_params";
103+
104+
private static final Logger LOG = LoggerFactory.getLogger(HttpAPIClientHelper.class);
102105

103106
private static final int ERROR_BODY_BUFFER_SIZE = 1024; // Error messages are usually small
104107

@@ -567,11 +570,9 @@ private void addQueryParams(URIBuilder req, Map<String, Object> requestConfig) {
567570
if (requestConfig.containsKey(ClientConfigProperties.QUERY_ID.getKey())) {
568571
req.addParameter(ClickHouseHttpProto.QPARAM_QUERY_ID, requestConfig.get(ClientConfigProperties.QUERY_ID.getKey()).toString());
569572
}
570-
if (requestConfig.containsKey("statement_params")) {
571-
Map<String, Object> params = (Map<String, Object>) requestConfig.get("statement_params");
572-
for (Map.Entry<String, Object> entry : params.entrySet()) {
573-
req.addParameter("param_" + entry.getKey(), String.valueOf(entry.getValue()));
574-
}
573+
if (requestConfig.containsKey(KEY_STATEMENT_PARAMS)) {
574+
Map<?, ?> params = (Map<?, ?>) requestConfig.get(KEY_STATEMENT_PARAMS);
575+
params.forEach((k, v) -> req.addParameter("param_" + k, String.valueOf(v)));
575576
}
576577

577578
boolean clientCompression = ClientConfigProperties.COMPRESS_CLIENT_REQUEST.getOrDefault(requestConfig);

0 commit comments

Comments
 (0)