Skip to content

Commit 9c309e2

Browse files
authored
Merge pull request #1763 from ClickHouse/feat_clientv2_timezone
[client-v2] Attach TimeZone to a QueryResponse & use TimeZone settings in binary readers
2 parents 3a82665 + 6c3a81b commit 9c309e2

File tree

22 files changed

+410
-99
lines changed

22 files changed

+410
-99
lines changed

clickhouse-cli-client/src/main/java/com/clickhouse/client/cli/ClickHouseCommandLineResponse.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ public class ClickHouseCommandLineResponse extends ClickHouseStreamResponse {
1414
private final transient ClickHouseCommandLine cli;
1515

1616
protected ClickHouseCommandLineResponse(ClickHouseConfig config, ClickHouseCommandLine cli) throws IOException {
17-
super(config, cli.getInputStream(), null, null, ClickHouseResponseSummary.EMPTY);
17+
super(config, cli.getInputStream(), null, null, ClickHouseResponseSummary.EMPTY, null);
1818
this.cli = cli;
1919

2020
if (processor.getInputStream().available() < 1) {

clickhouse-client/src/main/java/com/clickhouse/client/ClickHouseResponse.java

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import java.util.NoSuchElementException;
1010
import java.util.Spliterator;
1111
import java.util.Spliterators;
12+
import java.util.TimeZone;
1213
import java.util.stream.Stream;
1314
import java.util.stream.StreamSupport;
1415

@@ -39,7 +40,7 @@ public interface ClickHouseResponse extends AutoCloseable, Serializable {
3940
/**
4041
* Empty response that can never be closed.
4142
*/
42-
static final ClickHouseResponse EMPTY = new ClickHouseResponse() {
43+
ClickHouseResponse EMPTY = new ClickHouseResponse() {
4344
@Override
4445
public List<ClickHouseColumn> getColumns() {
4546
return Collections.emptyList();
@@ -75,6 +76,11 @@ public boolean isClosed() {
7576
// ensure the instance is "stateless"
7677
return false;
7778
}
79+
80+
@Override
81+
public TimeZone getTimeZone() {
82+
return null;
83+
}
7884
};
7985

8086
/**
@@ -102,6 +108,15 @@ public boolean isClosed() {
102108
*/
103109
ClickHouseInputStream getInputStream();
104110

111+
/**
112+
* Returns a server timezone if it is returned by server in a header {@code X-ClickHouse-Timezone } or
113+
* other way. If not, it returns null
114+
* @return server timezone from server response or null
115+
*/
116+
default TimeZone getTimeZone() {
117+
return null;
118+
}
119+
105120
/**
106121
* Gets the first record only. Please use {@link #records()} instead if you need
107122
* to access the rest of records.

clickhouse-client/src/main/java/com/clickhouse/client/ClickHouseSimpleResponse.java

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

3-
import java.util.ArrayList;
4-
import java.util.Collections;
5-
import java.util.LinkedList;
6-
import java.util.List;
7-
83
import com.clickhouse.data.ClickHouseColumn;
94
import com.clickhouse.data.ClickHouseInputStream;
105
import com.clickhouse.data.ClickHouseRecord;
@@ -13,12 +8,19 @@
138
import com.clickhouse.data.ClickHouseSimpleRecord;
149
import com.clickhouse.data.ClickHouseValue;
1510

11+
import java.util.ArrayList;
12+
import java.util.Collections;
13+
import java.util.LinkedList;
14+
import java.util.List;
15+
import java.util.TimeZone;
16+
1617
/**
1718
* A simple response built on top of two lists: columns and records.
1819
*/
1920
public class ClickHouseSimpleResponse implements ClickHouseResponse {
2021
private static final long serialVersionUID = 6883452584393840649L;
2122

23+
private final TimeZone timeZone;
2224
/**
2325
* Creates a response object using columns definition and raw values.
2426
*
@@ -28,7 +30,7 @@ public class ClickHouseSimpleResponse implements ClickHouseResponse {
2830
* @return response object
2931
*/
3032
public static ClickHouseResponse of(ClickHouseConfig config, List<ClickHouseColumn> columns, Object[][] values) {
31-
return of(config, columns, values, null);
33+
return of(config, columns, values, null, null);
3234
}
3335

3436
/**
@@ -41,7 +43,7 @@ public static ClickHouseResponse of(ClickHouseConfig config, List<ClickHouseColu
4143
* @return response object
4244
*/
4345
public static ClickHouseResponse of(ClickHouseConfig config, List<ClickHouseColumn> columns, Object[][] values,
44-
ClickHouseResponseSummary summary) {
46+
ClickHouseResponseSummary summary, TimeZone timeZone) {
4547
if (columns == null) {
4648
columns = Collections.emptyList();
4749
}
@@ -69,7 +71,7 @@ public static ClickHouseResponse of(ClickHouseConfig config, List<ClickHouseColu
6971
}
7072
}
7173

72-
return new ClickHouseSimpleResponse(columns, wrappedValues, summary);
74+
return new ClickHouseSimpleResponse(columns, wrappedValues, summary, timeZone);
7375
}
7476

7577
/**
@@ -118,7 +120,7 @@ public static ClickHouseResponse of(ClickHouseResponse response, ClickHouseRecor
118120
records.add(rec);
119121
}
120122

121-
return new ClickHouseSimpleResponse(response.getColumns(), records, response.getSummary());
123+
return new ClickHouseSimpleResponse(response.getColumns(), records, response.getSummary(), response.getTimeZone());
122124
}
123125

124126
private final List<ClickHouseColumn> columns;
@@ -129,14 +131,15 @@ public static ClickHouseResponse of(ClickHouseResponse response, ClickHouseRecor
129131
private volatile boolean closed;
130132

131133
protected ClickHouseSimpleResponse(List<ClickHouseColumn> columns, List<ClickHouseRecord> records,
132-
ClickHouseResponseSummary summary) {
134+
ClickHouseResponseSummary summary, TimeZone timeZone) {
133135
this.columns = columns;
134136
this.records = Collections.unmodifiableList(records);
135137
this.summary = summary != null ? summary : ClickHouseResponseSummary.EMPTY;
138+
this.timeZone = timeZone;
136139
}
137140

138141
protected ClickHouseSimpleResponse(List<ClickHouseColumn> columns, ClickHouseValue[][] values,
139-
ClickHouseResponseSummary summary) {
142+
ClickHouseResponseSummary summary, TimeZone timeZone) {
140143
this.columns = columns;
141144

142145
int len = values.length;
@@ -148,6 +151,7 @@ protected ClickHouseSimpleResponse(List<ClickHouseColumn> columns, ClickHouseVal
148151
this.records = Collections.unmodifiableList(list);
149152

150153
this.summary = summary != null ? summary : ClickHouseResponseSummary.EMPTY;
154+
this.timeZone = timeZone;
151155
}
152156

153157
@Override
@@ -165,6 +169,11 @@ public ClickHouseInputStream getInputStream() {
165169
throw new UnsupportedOperationException("An in-memory response does not have input stream");
166170
}
167171

172+
@Override
173+
public TimeZone getTimeZone() {
174+
return timeZone;
175+
}
176+
168177
@Override
169178
public Iterable<ClickHouseRecord> records() {
170179
return records;

clickhouse-client/src/main/java/com/clickhouse/client/ClickHouseStreamResponse.java

Lines changed: 34 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import java.util.Collections;
66
import java.util.List;
77
import java.util.Map;
8+
import java.util.TimeZone;
89

910
import com.clickhouse.data.ClickHouseColumn;
1011
import com.clickhouse.data.ClickHouseDataProcessor;
@@ -23,32 +24,35 @@ public class ClickHouseStreamResponse implements ClickHouseResponse {
2324

2425
private static final long serialVersionUID = 2271296998310082447L;
2526

27+
private final TimeZone timeZone;
28+
2629
protected static final List<ClickHouseColumn> defaultTypes = Collections
2730
.singletonList(ClickHouseColumn.of("results", "Nullable(String)"));
28-
29-
public static ClickHouseResponse of(ClickHouseConfig config, ClickHouseInputStream input) throws IOException {
30-
return of(config, input, null, null, null);
31-
}
32-
33-
public static ClickHouseResponse of(ClickHouseConfig config, ClickHouseInputStream input,
34-
Map<String, Serializable> settings) throws IOException {
35-
return of(config, input, settings, null, null);
36-
}
37-
38-
public static ClickHouseResponse of(ClickHouseConfig config, ClickHouseInputStream input,
39-
List<ClickHouseColumn> columns) throws IOException {
40-
return of(config, input, null, columns, null);
41-
}
42-
43-
public static ClickHouseResponse of(ClickHouseConfig config, ClickHouseInputStream input,
44-
Map<String, Serializable> settings, List<ClickHouseColumn> columns) throws IOException {
45-
return of(config, input, settings, columns, null);
46-
}
47-
31+
//
32+
// public static ClickHouseResponse of(ClickHouseConfig config, ClickHouseInputStream input) throws IOException {
33+
// return of(config, input, null, null, null);
34+
// }
35+
//
36+
// public static ClickHouseResponse of(ClickHouseConfig config, ClickHouseInputStream input,
37+
// Map<String, Serializable> settings) throws IOException {
38+
// return of(config, input, settings, null, null);
39+
// }
40+
//
41+
// public static ClickHouseResponse of(ClickHouseConfig config, ClickHouseInputStream input,
42+
// List<ClickHouseColumn> columns) throws IOException {
43+
// return of(config, input, null, columns, null);
44+
// }
45+
//
46+
// public static ClickHouseResponse of(ClickHouseConfig config, ClickHouseInputStream input,
47+
// Map<String, Serializable> settings, List<ClickHouseColumn> columns) throws IOException {
48+
// return of(config, input, settings, columns, null);
49+
// }
50+
//
4851
public static ClickHouseResponse of(ClickHouseConfig config, ClickHouseInputStream input,
49-
Map<String, Serializable> settings, List<ClickHouseColumn> columns, ClickHouseResponseSummary summary)
52+
Map<String, Serializable> settings, List<ClickHouseColumn> columns,
53+
ClickHouseResponseSummary summary, TimeZone timeZone)
5054
throws IOException {
51-
return new ClickHouseStreamResponse(config, input, settings, columns, summary);
55+
return new ClickHouseStreamResponse(config, input, settings, columns, summary, timeZone);
5256
}
5357

5458
protected final ClickHouseConfig config;
@@ -58,9 +62,11 @@ public static ClickHouseResponse of(ClickHouseConfig config, ClickHouseInputStre
5862
private volatile boolean closed;
5963

6064
protected ClickHouseStreamResponse(ClickHouseConfig config, ClickHouseInputStream input,
61-
Map<String, Serializable> settings, List<ClickHouseColumn> columns, ClickHouseResponseSummary summary)
65+
Map<String, Serializable> settings, List<ClickHouseColumn> columns, ClickHouseResponseSummary summary,
66+
TimeZone timeZone)
6267
throws IOException {
6368

69+
this.timeZone = timeZone;
6470
boolean hasError = true;
6571
try {
6672
this.processor = ClickHouseDataStreamFactory.getInstance().getProcessor(config, input, null, settings,
@@ -144,6 +150,11 @@ public Iterable<ClickHouseRecord> records() {
144150
return processor.records();
145151
}
146152

153+
@Override
154+
public TimeZone getTimeZone() {
155+
return timeZone;
156+
}
157+
147158
@Override
148159
public <T> Iterable<T> records(Class<T> objClass) {
149160
if (processor == null) {

clickhouse-grpc-client/src/main/java/com/clickhouse/client/grpc/ClickHouseGrpcResponse.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import java.io.Serializable;
55
import java.io.UncheckedIOException;
66
import java.util.Map;
7+
import java.util.TimeZone;
78
import java.util.concurrent.TimeUnit;
89

910
import com.clickhouse.client.ClickHouseConfig;
@@ -28,7 +29,7 @@ static void checkError(Result result) {
2829

2930
protected ClickHouseGrpcResponse(ClickHouseConfig config, Map<String, Serializable> settings,
3031
ClickHouseStreamObserver observer) throws IOException {
31-
super(config, observer.getInputStream(), settings, null, observer.getSummary());
32+
super(config, observer.getInputStream(), settings, null, observer.getSummary(), null);
3233

3334
this.observer = observer;
3435
}
@@ -42,7 +43,8 @@ protected ClickHouseGrpcResponse(ClickHouseConfig config, Map<String, Serializab
4243
: ClickHouseGrpcClientImpl.getInput(config, result.getOutput().newInput(),
4344
() -> checkError(result)),
4445
settings, null,
45-
new ClickHouseResponseSummary(null, null));
46+
new ClickHouseResponseSummary(null, null),
47+
TimeZone.getTimeZone(result.getTimeZone()));
4648

4749
this.observer = null;
4850
if (result.hasProgress()) {

clickhouse-http-client/src/main/java/com/clickhouse/client/http/ApacheHttpConnectionImpl.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,8 +128,8 @@ private ClickHouseHttpResponse buildResponse(ClickHouseConfig config, CloseableH
128128
format = ClickHouseFormat.valueOf(value);
129129
hasQueryResult = true;
130130
}
131-
value = getResponseHeader(response, ClickHouseHttpProto.HEADER_TIMEZONE, "");
132-
timeZone = !ClickHouseChecker.isNullOrEmpty(value) ? TimeZone.getTimeZone(value)
131+
String tzValue = getResponseHeader(response, ClickHouseHttpProto.HEADER_TIMEZONE, "");
132+
timeZone = !ClickHouseChecker.isNullOrEmpty(tzValue) ? TimeZone.getTimeZone(tzValue)
133133
: timeZone;
134134
}
135135

clickhouse-http-client/src/main/java/com/clickhouse/client/http/ClickHouseHttpClient.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ protected ClickHouseResponse send(ClickHouseRequest<?> sealedRequest) throws Cli
212212

213213

214214
return ClickHouseStreamResponse.of(httpResponse.getConfig(sealedRequest), httpResponse.getInputStream(),
215-
sealedRequest.getSettings(), null, httpResponse.summary);
215+
sealedRequest.getSettings(), null, httpResponse.summary, httpResponse.getTimeZone());
216216
}
217217

218218
@Override

clickhouse-http-client/src/main/java/com/clickhouse/client/http/ClickHouseHttpResponse.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,4 +81,8 @@ public ClickHouseHttpResponse(ClickHouseHttpConnection connection, ClickHouseInp
8181
public ClickHouseInputStream getInputStream() {
8282
return input;
8383
}
84+
85+
public TimeZone getTimeZone() {
86+
return timeZone;
87+
}
8488
}

clickhouse-jdbc/src/main/java/com/clickhouse/jdbc/internal/ClickHouseStatementImpl.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
import java.util.List;
5656
import java.util.Map;
5757
import java.util.Map.Entry;
58+
import java.util.TimeZone;
5859
import java.util.concurrent.TimeUnit;
5960
import java.util.concurrent.TimeoutException;
6061
import java.util.function.Function;
@@ -222,8 +223,10 @@ protected ClickHouseResponse processSqlStatement(ClickHouseSqlStatement stmt) th
222223

223224
f = getFile(f, stmt);
224225
final ClickHouseResponseSummary summary = new ClickHouseResponseSummary(null, null);
226+
TimeZone responseTimeZone = null;
225227
try (ClickHouseResponse response = request.query(stmt.getSQL()).output(f).executeAndWait()) {
226228
summary.add(response.getSummary());
229+
responseTimeZone = response.getTimeZone();
227230
} catch (ClickHouseException e) {
228231
throw SqlExceptionUtils.handle(e);
229232
}
@@ -236,7 +239,8 @@ protected ClickHouseResponse processSqlStatement(ClickHouseSqlStatement stmt) th
236239
new Object[][] { { file, f.getFormat().name(),
237240
f.hasCompression() ? f.getCompressionAlgorithm().encoding() : "none",
238241
f.getCompressionLevel(), f.getFile().length() } },
239-
summary);
242+
summary,
243+
responseTimeZone);
240244
} else if (stmt.getStatementType() == StatementType.INSERT) {
241245
final Mutation m = request.write().query(stmt.getSQL());
242246
final ClickHouseResponseSummary summary = new ClickHouseResponseSummary(null, null);
@@ -267,7 +271,7 @@ protected ClickHouseResponse processSqlStatement(ClickHouseSqlStatement stmt) th
267271
} catch (IOException e) {
268272
throw SqlExceptionUtils.handle(e);
269273
}
270-
return ClickHouseSimpleResponse.of(null, null, new Object[0][], summary);
274+
return ClickHouseSimpleResponse.of(null, null, new Object[0][], summary, null);
271275
}
272276
}
273277

0 commit comments

Comments
 (0)