Skip to content

Commit 15d30e0

Browse files
committed
Merge branch 'main' into jdbc_fix_nested_types
2 parents 765524b + b7ce67c commit 15d30e0

File tree

24 files changed

+897
-215
lines changed

24 files changed

+897
-215
lines changed

.github/workflows/analysis.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,14 +92,14 @@ jobs:
9292
- name: Build and install
9393
run: |
9494
find . -type f -name "simplelogger.*" -exec rm -fv '{}' \;
95-
mvn -q --batch-mode -DclickhouseVersion=$PREFERRED_LTS_VERSION \
95+
mvn -q --no-transfer-progress --batch-mode -DclickhouseVersion=$PREFERRED_LTS_VERSION \
9696
-DskipTests install
9797
- name: Analyze
9898
env:
9999
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any
100100
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
101101
run: |
102-
mvn --batch-mode -DclickhouseVersion=$PREFERRED_LTS_VERSION \
102+
mvn -fn --no-transfer-progress --batch-mode -DclickhouseVersion=$PREFERRED_LTS_VERSION \
103103
-Panalysis verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar -Dsonar.projectKey=ClickHouse_clickhouse-java
104104
continue-on-error: true
105105
- name: Generate and post coverage report

.github/workflows/nightly.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ jobs:
6868
with:
6969
maven_profiles: release
7070
maven_args: -q --batch-mode -DclickhouseVersion=${{ env.CH_VERSION }}
71+
server_id: central
7172
gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }}
7273
gpg_passphrase: ${{ secrets.GPG_PASSPHRASE }}
7374
nexus_username: ${{ secrets.SONATYPE_TOKEN_USER }}
@@ -78,6 +79,7 @@ jobs:
7879
directory: clickhouse-r2dbc
7980
maven_profiles: release
8081
maven_args: -q --batch-mode -Dr2dbc-spi.version=0.9.1.RELEASE -DclickhouseVersion=${{ env.CH_VERSION }}
82+
server_id: central
8183
gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }}
8284
gpg_passphrase: ${{ secrets.GPG_PASSPHRASE }}
8385
nexus_username: ${{ secrets.SONATYPE_TOKEN_USER }}

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ java.prof
4848
jmh-result.*
4949
profile.html
5050
jdbc-v2/gen
51+
jdbc-v2/src/main/antlr4/com/clickhouse/jdbc/internal/gen
52+
jdbc-v2/src/main/antlr4/com/clickhouse/jdbc/internal/ClickHouseLexer.tokens
5153

5254
# Shell scripts
5355
*.sh

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1218,7 +1218,7 @@ public CompletableFuture<InsertResponse> insert(String tableName, List<?> data,
12181218
Integer retry = (Integer) configuration.get(ClientConfigProperties.RETRY_ON_FAILURE.getKey());
12191219
final int maxRetries = retry == null ? 0 : retry;
12201220

1221-
settings.setOption(ClientConfigProperties.INPUT_OUTPUT_FORMAT.getKey(), format.name());
1221+
settings.setOption(ClientConfigProperties.INPUT_OUTPUT_FORMAT.getKey(), format);
12221222
final InsertSettings finalSettings = new InsertSettings(buildRequestSettings(settings.getAllSettings()));
12231223
Supplier<InsertResponse> supplier = () -> {
12241224
long startTime = System.nanoTime();
@@ -1421,7 +1421,7 @@ public CompletableFuture<InsertResponse> insert(String tableName,
14211421
throw new IllegalArgumentException("Buffer size must be greater than 0");
14221422
}
14231423

1424-
settings.setOption(ClientConfigProperties.INPUT_OUTPUT_FORMAT.getKey(), format.name());
1424+
settings.setOption(ClientConfigProperties.INPUT_OUTPUT_FORMAT.getKey(), format);
14251425
final InsertSettings finalSettings = new InsertSettings(buildRequestSettings(settings.getAllSettings()));
14261426

14271427
StringBuilder sqlStmt = new StringBuilder("INSERT INTO ").append(tableName);

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,9 @@ public static Map<String, Object> parseConfigMap(Map<String, String> configMap)
333333
}
334334
}
335335

336-
LOG.warn("Unknown and unmapped config properties: {}", tmpMap);
336+
if (!tmpMap.isEmpty()) {
337+
LOG.warn("Unknown and unmapped config properties: {}", tmpMap);
338+
}
337339

338340
return parsedConfig;
339341
}

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

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

33
import com.clickhouse.client.ClickHouseSslContextProvider;
4-
import com.clickhouse.client.api.*;
4+
import com.clickhouse.client.api.ClickHouseException;
5+
import com.clickhouse.client.api.Client;
6+
import com.clickhouse.client.api.ClientConfigProperties;
7+
import com.clickhouse.client.api.ClientException;
8+
import com.clickhouse.client.api.ClientFaultCause;
9+
import com.clickhouse.client.api.ClientMisconfigurationException;
10+
import com.clickhouse.client.api.ConnectionInitiationException;
11+
import com.clickhouse.client.api.ConnectionReuseStrategy;
12+
import com.clickhouse.client.api.DataTransferException;
13+
import com.clickhouse.client.api.ServerException;
514
import com.clickhouse.client.api.enums.ProxyType;
615
import com.clickhouse.client.api.http.ClickHouseHttpProto;
716
import com.clickhouse.client.api.transport.Endpoint;
17+
import com.clickhouse.data.ClickHouseFormat;
818
import net.jpountz.lz4.LZ4Factory;
919
import org.apache.hc.client5.http.ConnectTimeoutException;
1020
import org.apache.hc.client5.http.classic.methods.HttpPost;
@@ -55,6 +65,7 @@
5565
import java.io.IOException;
5666
import java.io.InputStream;
5767
import java.io.OutputStream;
68+
import java.io.UnsupportedEncodingException;
5869
import java.lang.reflect.Method;
5970
import java.net.ConnectException;
6071
import java.net.InetSocketAddress;
@@ -63,6 +74,7 @@
6374
import java.net.SocketTimeoutException;
6475
import java.net.URI;
6576
import java.net.URISyntaxException;
77+
import java.net.URLEncoder;
6678
import java.net.UnknownHostException;
6779
import java.nio.charset.StandardCharsets;
6880
import java.security.NoSuchAlgorithmException;
@@ -79,12 +91,16 @@
7991
import java.util.concurrent.TimeUnit;
8092
import java.util.concurrent.atomic.AtomicLong;
8193
import java.util.function.Function;
94+
import java.util.regex.Pattern;
8295

8396
public class HttpAPIClientHelper {
8497
private static final Logger LOG = LoggerFactory.getLogger(Client.class);
8598

8699
private static final int ERROR_BODY_BUFFER_SIZE = 1024; // Error messages are usually small
87100

101+
private static final Pattern PATTERN_HEADER_VALUE_ASCII = Pattern.compile(
102+
"\\p{Graph}+(?:[ ]\\p{Graph}+)*");
103+
88104
private final CloseableHttpClient httpClient;
89105

90106
private final RequestConfig baseRequestConfig;
@@ -287,7 +303,7 @@ public CloseableHttpClient createHttpClient(boolean initSslContext, Map<String,
287303
SocketConfig socketConfig = soCfgBuilder.build();
288304

289305
// Connection manager
290-
if (ClientConfigProperties.CONNECTION_POOL_ENABLED.getOrDefault(configuration)) {
306+
if (ClientConfigProperties.CONNECTION_POOL_ENABLED.<Boolean>getOrDefault(configuration)) {
291307
clientBuilder.setConnectionManager(poolConnectionManager(sslConnectionSocketFactory, socketConfig, configuration));
292308
} else {
293309
clientBuilder.setConnectionManager(basicConnectionManager(sslConnectionSocketFactory, socketConfig, configuration));
@@ -430,36 +446,55 @@ public ClassicHttpResponse executeRequest(Endpoint server, Map<String, Object> r
430446
private static final ContentType CONTENT_TYPE = ContentType.create(ContentType.TEXT_PLAIN.getMimeType(), "UTF-8");
431447

432448
private void addHeaders(HttpPost req, Map<String, Object> requestConfig) {
433-
req.addHeader(HttpHeaders.CONTENT_TYPE, CONTENT_TYPE.getMimeType());
449+
addHeader(req, HttpHeaders.CONTENT_TYPE, CONTENT_TYPE.getMimeType());
434450
if (requestConfig.containsKey(ClientConfigProperties.INPUT_OUTPUT_FORMAT.getKey())) {
435-
req.addHeader(ClickHouseHttpProto.HEADER_FORMAT, requestConfig.get(ClientConfigProperties.INPUT_OUTPUT_FORMAT.getKey()));
451+
addHeader(
452+
req,
453+
ClickHouseHttpProto.HEADER_FORMAT,
454+
((ClickHouseFormat) requestConfig.get(ClientConfigProperties.INPUT_OUTPUT_FORMAT.getKey())).name());
436455
}
437-
438456
if (requestConfig.containsKey(ClientConfigProperties.QUERY_ID.getKey())) {
439-
req.addHeader(ClickHouseHttpProto.HEADER_QUERY_ID, requestConfig.get(ClientConfigProperties.QUERY_ID.getKey()).toString());
440-
}
441-
442-
443-
req.addHeader(ClickHouseHttpProto.HEADER_DATABASE, ClientConfigProperties.DATABASE.getOrDefault(requestConfig));
444-
445-
446-
if (ClientConfigProperties.SSL_AUTH.getOrDefault(requestConfig)) {
447-
req.addHeader(ClickHouseHttpProto.HEADER_DB_USER, ClientConfigProperties.USER.getOrDefault(requestConfig));
448-
req.addHeader(ClickHouseHttpProto.HEADER_SSL_CERT_AUTH, "on");
449-
} else if (ClientConfigProperties.HTTP_USE_BASIC_AUTH.getOrDefault(requestConfig)) {
457+
addHeader(
458+
req,
459+
ClickHouseHttpProto.HEADER_QUERY_ID,
460+
(String) requestConfig.get(ClientConfigProperties.QUERY_ID.getKey()));
461+
}
462+
addHeader(
463+
req,
464+
ClickHouseHttpProto.HEADER_DATABASE,
465+
ClientConfigProperties.DATABASE.getOrDefault(requestConfig));
466+
467+
if (ClientConfigProperties.SSL_AUTH.<Boolean>getOrDefault(requestConfig).booleanValue()) {
468+
addHeader(
469+
req,
470+
ClickHouseHttpProto.HEADER_DB_USER,
471+
ClientConfigProperties.USER.getOrDefault(requestConfig));
472+
addHeader(
473+
req,
474+
ClickHouseHttpProto.HEADER_SSL_CERT_AUTH,
475+
"on");
476+
} else if (ClientConfigProperties.HTTP_USE_BASIC_AUTH.<Boolean>getOrDefault(requestConfig).booleanValue()) {
450477
String user = ClientConfigProperties.USER.getOrDefault(requestConfig);
451478
String password = ClientConfigProperties.PASSWORD.getOrDefault(requestConfig);
452-
453-
req.addHeader(HttpHeaders.AUTHORIZATION, "Basic " + Base64.getEncoder().encodeToString(
454-
(user + ":" + password).getBytes(StandardCharsets.UTF_8))
455-
);
479+
// Use as-is, no encoding allowed
480+
req.addHeader(
481+
HttpHeaders.AUTHORIZATION,
482+
"Basic " + Base64.getEncoder().encodeToString(
483+
(user + ":" + password).getBytes(StandardCharsets.UTF_8)));
456484
} else {
457-
req.addHeader(ClickHouseHttpProto.HEADER_DB_USER, ClientConfigProperties.USER.getOrDefault(requestConfig));
458-
req.addHeader(ClickHouseHttpProto.HEADER_DB_PASSWORD, ClientConfigProperties.PASSWORD.getOrDefault(requestConfig));
459-
485+
addHeader(
486+
req,
487+
ClickHouseHttpProto.HEADER_DB_USER,
488+
ClientConfigProperties.USER.getOrDefault(requestConfig));
489+
addHeader(
490+
req,
491+
ClickHouseHttpProto.HEADER_DB_PASSWORD,
492+
ClientConfigProperties.PASSWORD.getOrDefault(requestConfig));
460493
}
461494
if (proxyAuthHeaderValue != null) {
462-
req.addHeader(HttpHeaders.PROXY_AUTHORIZATION, proxyAuthHeaderValue);
495+
req.addHeader(
496+
HttpHeaders.PROXY_AUTHORIZATION,
497+
proxyAuthHeaderValue);
463498
}
464499

465500
boolean clientCompression = ClientConfigProperties.COMPRESS_CLIENT_REQUEST.getOrDefault(requestConfig);
@@ -469,26 +504,30 @@ private void addHeaders(HttpPost req, Map<String, Object> requestConfig) {
469504

470505
if (useHttpCompression) {
471506
if (serverCompression) {
472-
req.addHeader(HttpHeaders.ACCEPT_ENCODING, "lz4");
507+
addHeader(req, HttpHeaders.ACCEPT_ENCODING, "lz4");
473508
}
474509
if (clientCompression && !appCompressedData) {
475-
req.addHeader(HttpHeaders.CONTENT_ENCODING, "lz4");
510+
addHeader(req, HttpHeaders.CONTENT_ENCODING, "lz4");
476511
}
477512
}
478513

479514
for (String key : requestConfig.keySet()) {
480515
if (key.startsWith(ClientConfigProperties.HTTP_HEADER_PREFIX)) {
481516
Object val = requestConfig.get(key);
482517
if (val != null) {
483-
req.setHeader(key.substring(ClientConfigProperties.HTTP_HEADER_PREFIX.length()), String.valueOf(val));
518+
addHeader(
519+
req,
520+
key.substring(ClientConfigProperties.HTTP_HEADER_PREFIX.length()),
521+
String.valueOf(val));
484522
}
485523
}
486524
}
487525

488-
489526
// Special cases
490-
if (req.containsHeader(HttpHeaders.AUTHORIZATION) && (req.containsHeader(ClickHouseHttpProto.HEADER_DB_USER) ||
491-
req.containsHeader(ClickHouseHttpProto.HEADER_DB_PASSWORD))) {
527+
if (req.containsHeader(HttpHeaders.AUTHORIZATION)
528+
&& (req.containsHeader(ClickHouseHttpProto.HEADER_DB_USER) ||
529+
req.containsHeader(ClickHouseHttpProto.HEADER_DB_PASSWORD)))
530+
{
492531
// user has set auth header for purpose, lets remove ours
493532
req.removeHeaders(ClickHouseHttpProto.HEADER_DB_USER);
494533
req.removeHeaders(ClickHouseHttpProto.HEADER_DB_PASSWORD);
@@ -668,7 +707,6 @@ private void correctUserAgentHeader(HttpRequest request, Map<String, Object> req
668707
} else if (userAgentHeader != null) {
669708
userAgentValue = userAgentHeader.getValue() + " " + defaultUserAgent;
670709
}
671-
672710
request.setHeader(HttpHeaders.USER_AGENT, userAgentValue);
673711
}
674712

@@ -720,6 +758,29 @@ public void close() {
720758
httpClient.close(CloseMode.IMMEDIATE);
721759
}
722760

761+
private static <T> void addHeader(HttpRequest req, String headerName,
762+
String value)
763+
{
764+
if (value == null) {
765+
return;
766+
}
767+
768+
if (value.trim().isEmpty()) {
769+
return;
770+
}
771+
if (PATTERN_HEADER_VALUE_ASCII.matcher(value).matches()) {
772+
req.addHeader(headerName, value);
773+
} else {
774+
try {
775+
req.addHeader(
776+
headerName + "*",
777+
"UTF-8''" + URLEncoder.encode(value, StandardCharsets.UTF_8.name()));
778+
} catch (UnsupportedEncodingException e) {
779+
throw new ClientException("Failed to convert string to UTF8" , e);
780+
}
781+
}
782+
}
783+
723784
/**
724785
* This factory is used only when no ssl connections are required (no https endpoints).
725786
* Internally http client would create factory and spend time if no supplied.

examples/client-v2/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545
<!-- <repository>-->
4646
<!-- <id>ossrh</id>-->
4747
<!-- <name>Sonatype OSSRH</name>-->
48-
<!-- <url>https://s01.oss.sonatype.org/content/repositories/snapshots/</url>-->
48+
<!-- <url>https://central.sonatype.com/repository/maven-snapshots/</url>-->
4949
<!-- </repository>-->
5050
</repositories>
5151

examples/client/pom.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
<repository>
3232
<id>ossrh</id>
3333
<name>Sonatype OSSRH</name>
34-
<url>https://s01.oss.sonatype.org/content/repositories/snapshots/</url>
34+
<url>https://central.sonatype.com/repository/maven-snapshots/</url>
3535
</repository>
3636
</repositories>
3737

@@ -41,7 +41,7 @@
4141
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
4242

4343
<clickhouse-java.version>0.9.0-SNAPSHOT</clickhouse-java.version>
44-
<!-- Nightly snapshot version from https://s01.oss.sonatype.org/content/repositories/snapshots/ or latest from local -->
44+
<!-- Nightly snapshot version from https://central.sonatype.com/repository/maven-snapshots/or latest from local -->
4545
<!-- <clickhouse-java.version>0.9.0-SNAPSHOT</clickhouse-java.version>-->
4646

4747
<apache-httpclient.version>5.2.1</apache-httpclient.version>

examples/demo-kotlin-service/build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ application {
2121
repositories {
2222
mavenLocal() // comment to pull nightly builds instead of local cache
2323
mavenCentral()
24-
maven("https://s01.oss.sonatype.org/content/repositories/snapshots/") // for nightly builds
24+
maven("https://central.sonatype.com/repository/maven-snapshots/") // for nightly builds
2525
}
2626

2727
val ch_java_client_version: String by extra

examples/demo-service/build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ configurations {
2222
repositories {
2323
mavenLocal() // comment to pull nightly builds instead of local cache
2424
mavenCentral()
25-
maven("https://s01.oss.sonatype.org/content/repositories/snapshots/") // for nightly builds
25+
maven("https://central.sonatype.com/repository/maven-snapshots/")
2626
}
2727

2828
val ch_java_client_version: String by extra

0 commit comments

Comments
 (0)