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 @@ -1338,7 +1338,7 @@ public CompletableFuture<InsertResponse> insert(String tableName, List<?> data,
String queryId = HttpAPIClientHelper.getHeaderVal(httpResponse.getFirstHeader(ClickHouseHttpProto.HEADER_QUERY_ID), requestSettings.getQueryId(), String::valueOf);
metrics.operationComplete();
metrics.setQueryId(queryId);
return new InsertResponse(metrics);
return new InsertResponse(metrics, HttpAPIClientHelper.collectResponseHeaders(httpResponse));
} catch (Exception e) {
String msg = requestExMsg("Insert", (i + 1), durationSince(startTime).toMillis(), requestSettings.getQueryId());
lastException = httpClientHelper.wrapException(msg, e, requestSettings.getQueryId());
Expand Down Expand Up @@ -1545,7 +1545,7 @@ public CompletableFuture<InsertResponse> insert(String tableName,
String queryId = HttpAPIClientHelper.getHeaderVal(httpResponse.getFirstHeader(ClickHouseHttpProto.HEADER_QUERY_ID), requestSettings.getQueryId(), String::valueOf);
metrics.operationComplete();
metrics.setQueryId(queryId);
return new InsertResponse(metrics);
return new InsertResponse(metrics, HttpAPIClientHelper.collectResponseHeaders(httpResponse));
} catch (Exception e) {
String msg = requestExMsg("Insert", (i + 1), durationSince(startTime).toMillis(), requestSettings.getQueryId());
lastException = httpClientHelper.wrapException(msg, e, requestSettings.getQueryId());
Expand Down Expand Up @@ -1684,7 +1684,8 @@ public CompletableFuture<QueryResponse> query(String sqlQuery, Map<String, Objec
responseFormat = ClickHouseFormat.valueOf(formatHeader.getValue());
}

return new QueryResponse(httpResponse, responseFormat, requestSettings, metrics);
return new QueryResponse(httpResponse, responseFormat, requestSettings, metrics,
HttpAPIClientHelper.collectResponseHeaders(httpResponse));

} catch (Exception e) {
HttpAPIClientHelper.closeQuietly(httpResponse);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
import com.clickhouse.client.api.metrics.ServerMetrics;
import com.clickhouse.client.api.query.QueryResponse;

import java.util.Map;

public class CommandResponse implements AutoCloseable {

private final QueryResponse response;
Expand Down Expand Up @@ -72,6 +74,25 @@ public long getServerTime() {
return response.getServerTime();
}

/**
* Returns the value of {@code X-ClickHouse-Server-Display-Name} response header.
*
* @return server display name or {@code null} if not present
*/
public String getServerDisplayName() {
return response.getServerDisplayName();
}

/**
* Returns all collected response headers as an unmodifiable map.
* Only whitelisted ClickHouse headers are included.
*
* @return map of header name to header value
*/
public Map<String, String> getResponseHeaders() {
return response.getResponseHeaders();
}

@Override
public void close() throws Exception {
response.close();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,23 @@
package com.clickhouse.client.api.insert;

import com.clickhouse.client.api.http.ClickHouseHttpProto;
import com.clickhouse.client.api.metrics.OperationMetrics;
import com.clickhouse.client.api.metrics.ServerMetrics;

import java.util.Collections;
import java.util.Map;

public class InsertResponse implements AutoCloseable {
private OperationMetrics operationMetrics;
private final Map<String, String> responseHeaders;

public InsertResponse(OperationMetrics metrics) {
this(metrics, Collections.emptyMap());
}

public InsertResponse(OperationMetrics metrics, Map<String, String> responseHeaders) {
this.operationMetrics = metrics;
this.responseHeaders = responseHeaders;
}

@Override
Expand Down Expand Up @@ -78,4 +88,23 @@ public long getResultRows() {
public String getQueryId() {
return operationMetrics.getQueryId();
}

/**
* Returns the value of {@code X-ClickHouse-Server-Display-Name} response header.
*
* @return server display name or {@code null} if not present
*/
public String getServerDisplayName() {
return responseHeaders.get(ClickHouseHttpProto.HEADER_SRV_DISPLAY_NAME);
}

/**
* Returns all collected response headers as an unmodifiable map.
* Only whitelisted ClickHouse headers are included.
*
* @return map of header name to header value
*/
public Map<String, String> getResponseHeaders() {
return responseHeaders;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@
import java.util.Objects;
import java.util.Optional;
import java.util.Properties;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Set;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.TimeUnit;
Expand Down Expand Up @@ -752,6 +754,31 @@ public static int getHeaderInt(Header header, int defaultValue) {
return getHeaderVal(header, defaultValue, Integer::parseInt);
}

private static final Set<String> RESPONSE_HEADER_WHITELIST = new HashSet<>(Arrays.asList(
ClickHouseHttpProto.HEADER_QUERY_ID,
ClickHouseHttpProto.HEADER_SRV_SUMMARY,
ClickHouseHttpProto.HEADER_SRV_DISPLAY_NAME,
ClickHouseHttpProto.HEADER_DATABASE,
ClickHouseHttpProto.HEADER_DB_USER
));

/**
* Collects whitelisted response headers from an HTTP response into a map.
*
* @param response the HTTP response
* @return unmodifiable map of header name to header value for whitelisted headers present in the response
*/
public static Map<String, String> collectResponseHeaders(ClassicHttpResponse response) {
Map<String, String> headers = new HashMap<>();
for (String name : RESPONSE_HEADER_WHITELIST) {
Header header = response.getFirstHeader(name);
if (header != null) {
headers.put(name, header.getValue());
}
}
return Collections.unmodifiableMap(headers);
}

public static String getHeaderVal(Header header, String defaultValue) {
return getHeaderVal(header, defaultValue, Function.identity());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
import org.apache.hc.core5.http.Header;

import java.io.InputStream;
import java.util.Collections;
import java.util.Map;
import java.util.TimeZone;

/**
Expand All @@ -35,12 +37,20 @@ public class QueryResponse implements AutoCloseable {

private ClassicHttpResponse httpResponse;

private final Map<String, String> responseHeaders;

public QueryResponse(ClassicHttpResponse response, ClickHouseFormat format, QuerySettings settings,
OperationMetrics operationMetrics) {
this(response, format, settings, operationMetrics, Collections.emptyMap());
}

public QueryResponse(ClassicHttpResponse response, ClickHouseFormat format, QuerySettings settings,
OperationMetrics operationMetrics, Map<String, String> responseHeaders) {
this.httpResponse = response;
this.format = format;
this.operationMetrics = operationMetrics;
this.settings = settings;
this.responseHeaders = responseHeaders;

Header tzHeader = response.getFirstHeader(ClickHouseHttpProto.HEADER_TIMEZONE);
if (tzHeader != null) {
Expand Down Expand Up @@ -150,6 +160,25 @@ public String getQueryId() {
return operationMetrics.getQueryId();
}

/**
* Returns the value of {@code X-ClickHouse-Server-Display-Name} response header.
*
* @return server display name or {@code null} if not present
*/
public String getServerDisplayName() {
return responseHeaders.get(ClickHouseHttpProto.HEADER_SRV_DISPLAY_NAME);
}

/**
* Returns all collected response headers as an unmodifiable map.
* Only whitelisted ClickHouse headers are included.
*
* @return map of header name to header value
*/
public Map<String, String> getResponseHeaders() {
return responseHeaders;
}

public TimeZone getTimeZone() {
return settings.getOption(ClientConfigProperties.SERVER_TIMEZONE.getKey()) == null
? null
Expand Down
Loading