Skip to content

Commit 92e075d

Browse files
committed
Fix compile errors and test failures
1 parent 45c95d3 commit 92e075d

File tree

13 files changed

+163
-67
lines changed

13 files changed

+163
-67
lines changed

clickhouse-cli-client/README.md

+22-7
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,18 @@
11
# ClickHouse Command-line Client
22

3-
This is a wrapper of ClickHouse native command-line client. In order to use it, please make sure 1) either the native command-line client or docker is installed; and 2) `clickhouse_cli_path` or `docker_cli_path` is configured properly.
3+
This is a thin wrapper of ClickHouse native command-line client. It provides an alternative way to communicate with ClickHouse, which might be of use when you prefer:
44

5-
Unlike `clickhouse-http-client`, this module is not designed for dealing with many queries in short period of time, because it uses sub-process(NOT thread) and file-based streaming. Having said that, it provides an alternative, usually faster,way to dump and load large data sets. Besides, due to its simplicity, it can be used as an example to demonstrate how to implement SPI defined in `clickhouse-client`.
5+
- TCP/native protocol over HTTP or gRPC
6+
- native CLI client instead of pure Java implementation
7+
- an example of implementing SPI defined in `clickhouse-client` module
8+
9+
Either [clickhouse-client](https://clickhouse.com/docs/en/interfaces/cli/) or [docker](https://docs.docker.com/get-docker/) must be installed prior to use. And it's important to understand that this module uses sub-process(in addition to threads) and file-based streaming, meaning 1) it's not as fast as native CLI client or pure Java implementation, although it's close in the case of dumping and loading data; and 2) it's not suitable for scenarios like dealing with many queries in short period of time.
610

711
## Limitations and Known Issues
812

913
- Only `max_result_rows` and `result_overflow_mode` two settings are currently supported
1014
- ClickHouseResponseSummary is always empty - see ClickHouse/ClickHouse#37241
11-
- Session is not supported and query cannot be cancelled - see ClickHouse/ClickHouse#37308
15+
- Session is not supported - see ClickHouse/ClickHouse#37308
1216

1317
## Maven Dependency
1418

@@ -27,7 +31,7 @@ Unlike `clickhouse-http-client`, this module is not designed for dealing with ma
2731
// make sure 'clickhouse-client' or 'docker' is in PATH before you start the program
2832
// alternatively, configure CLI path in either Java system property or environment variable, for examples:
2933
// CHC_CLICKHOUSE_CLI_PATH=/path/to/clickhouse-client CHC_DOCKER_CLI_PATH=/path/to/docker java MyProgram
30-
// java -Dclickhouse_cli_path=/path/to/clickhouse-client -Ddocker_cli_path=/path/to/docker MyProgram
34+
// java -Dchc_clickhouse_cli_path=/path/to/clickhouse-client -Dchc_docker_cli_path=/path/to/docker MyProgram
3135

3236
// clickhouse-cli-client uses TCP protocol
3337
ClickHouseProtocol preferredProtocol = ClickHouseProtocol.TCP;
@@ -37,13 +41,13 @@ ClickHouseNode server = ClickHouseNode.builder().host("my-server").port(preferre
3741
// declares a file
3842
ClickHouseFile file = ClickHouseFile.of("data.csv");
3943

40-
// dump query results into the file - format is TSV, according to file extension
44+
// dump query results into the file - format is CSV, according to file extension
4145
ClickHouseClient.dump(server, "select * from some_table", file).get();
4246

43-
// now load it into my_table, using TSV format
47+
// now load it into my_table, using CSV format
4448
ClickHouseClient.load(server, "my_table", file).get();
4549

46-
// it can be used in the same as any other client
50+
// it can be used in the same way as any other client
4751
try (ClickHouseClient client = ClickHouseClient.newInstance(preferredProtocol);
4852
ClickHouseResponse response = client.connect(server)
4953
.query("select * from numbers(:limit)")
@@ -53,4 +57,15 @@ try (ClickHouseClient client = ClickHouseClient.newInstance(preferredProtocol);
5357
String str = r.getValue(0).asString();
5458
}
5559
}
60+
61+
// and of course it's part of JDBC driver
62+
try (Connection conn = DriverManager.getConnect("jdbc:ch:tcp://my-server", "default", "");
63+
PreparedStatement stmt = conn.preparedStatement("select * from numbers(?)")) {
64+
stmt.setInt(1, 1000);
65+
ResultSet rs = stmt.executeQuery();
66+
while (rs.next()) {
67+
int num = rs.getInt(1);
68+
String str = rs.getString(1);
69+
}
70+
}
5671
```

clickhouse-cli-client/pom.xml

+15-15
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,12 @@
2424
<groupId>${project.parent.groupId}</groupId>
2525
<artifactId>clickhouse-client</artifactId>
2626
<version>${revision}</version>
27-
</dependency>
28-
<dependency>
29-
<groupId>org.lz4</groupId>
30-
<artifactId>lz4-java</artifactId>
27+
<exclusions>
28+
<exclusion>
29+
<groupId>*</groupId>
30+
<artifactId>*</artifactId>
31+
</exclusion>
32+
</exclusions>
3133
</dependency>
3234

3335
<!-- necessary for Java 9+ -->
@@ -54,11 +56,6 @@
5456
<artifactId>testcontainers</artifactId>
5557
<scope>test</scope>
5658
</dependency>
57-
<dependency>
58-
<groupId>com.github.tomakehurst</groupId>
59-
<artifactId>wiremock-jre8</artifactId>
60-
<scope>test</scope>
61-
</dependency>
6259
<dependency>
6360
<groupId>org.testng</groupId>
6461
<artifactId>testng</artifactId>
@@ -83,12 +80,6 @@
8380
<createDependencyReducedPom>true</createDependencyReducedPom>
8481
<promoteTransitiveDependencies>true</promoteTransitiveDependencies>
8582
<shadedClassifierName>shaded</shadedClassifierName>
86-
<relocations>
87-
<relocation>
88-
<pattern>net.jpountz</pattern>
89-
<shadedPattern>${shade.base}.jpountz</shadedPattern>
90-
</relocation>
91-
</relocations>
9283
<transformers>
9384
<transformer implementation="org.apache.maven.plugins.shade.resource.ApacheLicenseResourceTransformer" />
9485
<transformer implementation="org.apache.maven.plugins.shade.resource.ApacheNoticeResourceTransformer" />
@@ -116,6 +107,15 @@
116107
<groupId>org.apache.maven.plugins</groupId>
117108
<artifactId>maven-compiler-plugin</artifactId>
118109
</plugin>
110+
<plugin>
111+
<groupId>org.apache.maven.plugins</groupId>
112+
<artifactId>maven-failsafe-plugin</artifactId>
113+
<configuration>
114+
<environmentVariables>
115+
<CHC_TEST_CONTAINER_ID>clickhouse-cli-client</CHC_TEST_CONTAINER_ID>
116+
</environmentVariables>
117+
</configuration>
118+
</plugin>
119119
</plugins>
120120
</build>
121121
</project>

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

+7-7
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@
88
import java.io.IOException;
99
import java.io.OutputStream;
1010
import java.io.UncheckedIOException;
11-
import java.lang.ProcessBuilder.Redirect;
1211
import java.nio.charset.StandardCharsets;
1312
import java.nio.file.Files;
1413
import java.nio.file.Path;
14+
import java.nio.file.Paths;
1515
import java.util.ArrayList;
1616
import java.util.Collections;
1717
import java.util.LinkedList;
@@ -60,7 +60,7 @@ static boolean check(int timeout, String command, String... args) {
6060
Collections.addAll(list, args);
6161
Process process = null;
6262
try {
63-
process = new ProcessBuilder(list).redirectError(Redirect.DISCARD).start();
63+
process = new ProcessBuilder(list).start();
6464
process.getOutputStream().close();
6565
if (process.waitFor(timeout, TimeUnit.MILLISECONDS)) {
6666
int exitValue = process.exitValue();
@@ -168,7 +168,7 @@ static Process startProcess(ClickHouseNode server, ClickHouseRequest<?> request)
168168
}
169169
if ((boolean) config.getOption(ClickHouseCommandLineOption.USE_CLI_CONFIG)) {
170170
str = (String) config.getOption(ClickHouseCommandLineOption.CLI_CONFIG_FILE);
171-
if (Files.exists(Path.of(str))) {
171+
if (Files.exists(Paths.get(str))) {
172172
commands.add("--config-file=".concat(str));
173173
}
174174
} else {
@@ -194,13 +194,13 @@ static Process startProcess(ClickHouseNode server, ClickHouseRequest<?> request)
194194
if (!tableFile.isAvailable() || !tableFile.getFile().getAbsolutePath().startsWith(hostDir)) {
195195
// creating a hard link is faster but it's not platform-independent
196196
File f = ClickHouseInputStream.save(
197-
Path.of(hostDir, "chc_".concat(UUID.randomUUID().toString())).toFile(),
197+
Paths.get(hostDir, "chc_".concat(UUID.randomUUID().toString())).toFile(),
198198
table.getContent(), config.getWriteBufferSize(), config.getSocketTimeout(), true);
199199
filePath = containerDir.concat(f.getName());
200200
} else {
201201
filePath = tableFile.getFile().getAbsolutePath();
202202
if (!hostDir.equals(containerDir)) {
203-
filePath = Path.of(containerDir, filePath.substring(hostDir.length())).toFile().getAbsolutePath();
203+
filePath = Paths.get(containerDir, filePath.substring(hostDir.length())).toFile().getAbsolutePath();
204204
}
205205
}
206206
commands.add("--file=" + filePath);
@@ -235,7 +235,7 @@ static Process startProcess(ClickHouseNode server, ClickHouseRequest<?> request)
235235
String workDirectory = (String) config.getOption(
236236
ClickHouseCommandLineOption.CLI_WORK_DIRECTORY);
237237
if (!ClickHouseChecker.isNullOrBlank(workDirectory)) {
238-
Path p = Path.of(workDirectory);
238+
Path p = Paths.get(workDirectory);
239239
if (Files.isDirectory(p)) {
240240
builder.directory(p.toFile());
241241
}
@@ -264,7 +264,7 @@ static Process startProcess(ClickHouseNode server, ClickHouseRequest<?> request)
264264
fileName = new StringBuilder(len + uuid.length() + 1).append(fileName).append('_')
265265
.append(UUID.randomUUID().toString()).toString();
266266
}
267-
Path newPath = Path.of(hostDir, fileName);
267+
Path newPath = Paths.get(hostDir, fileName);
268268
try {
269269
f = Files.createLink(newPath, f.toPath()).toFile();
270270
} catch (IOException e) {

clickhouse-cli-client/src/test/java/com/clickhouse/client/cli/ClickHouseCommandLineClientTest.java

+29-1
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,26 @@
11
package com.clickhouse.client.cli;
22

33
import com.clickhouse.client.ClickHouseClient;
4+
import com.clickhouse.client.ClickHouseClientBuilder;
5+
import com.clickhouse.client.ClickHouseNode;
46
import com.clickhouse.client.ClickHouseProtocol;
7+
import com.clickhouse.client.ClickHouseServerForTest;
58
import com.clickhouse.client.ClientIntegrationTest;
9+
import com.clickhouse.client.cli.config.ClickHouseCommandLineOption;
610

11+
import org.testcontainers.containers.GenericContainer;
712
import org.testng.Assert;
813
import org.testng.SkipException;
14+
import org.testng.annotations.BeforeClass;
915
import org.testng.annotations.Test;
1016

1117
public class ClickHouseCommandLineClientTest extends ClientIntegrationTest {
18+
@BeforeClass
19+
static void init() {
20+
System.setProperty(ClickHouseCommandLineOption.CLI_CONTAINER_DIRECTORY.getSystemProperty(),
21+
ClickHouseServerForTest.getClickHouseContainerTmpDir());
22+
}
23+
1224
@Override
1325
protected ClickHouseProtocol getProtocol() {
1426
return ClickHouseProtocol.TCP;
@@ -19,9 +31,25 @@ protected Class<? extends ClickHouseClient> getClientClass() {
1931
return ClickHouseCommandLineClient.class;
2032
}
2133

34+
@Override
35+
protected ClickHouseClientBuilder initClient(ClickHouseClientBuilder builder) {
36+
return super.initClient(builder).option(ClickHouseCommandLineOption.CLI_CONTAINER_DIRECTORY,
37+
ClickHouseServerForTest.getClickHouseContainerTmpDir());
38+
}
39+
40+
@Override
41+
protected ClickHouseNode getServer() {
42+
GenericContainer<?> container = ClickHouseServerForTest.getClickHouseContainer();
43+
if (container != null) {
44+
return ClickHouseNode.of("localhost", getProtocol(), getProtocol().getDefaultPort(), null);
45+
}
46+
47+
return super.getServer();
48+
}
49+
2250
@Test(groups = { "integration" })
2351
@Override
24-
public void testLoadRawData() {
52+
public void testLoadRawData() throws Exception {
2553
throw new SkipException("Skip due to response summary is always empty");
2654
}
2755

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

+4-9
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
package com.clickhouse.client;
22

3-
import java.io.FileNotFoundException;
4-
import java.io.IOException;
53
import java.io.InputStream;
64
import java.io.OutputStream;
75
import java.io.UncheckedIOException;
@@ -305,12 +303,10 @@ static CompletableFuture<ClickHouseResponseSummary> dump(ClickHouseNode server,
305303
* @throws IllegalArgumentException if any of server, tableOrQuery, and output
306304
* is null
307305
* @throws CompletionException when error occurred during execution
308-
* @throws IOException when failed to create the file or its parent
309-
* directories
310306
*/
311307
static CompletableFuture<ClickHouseResponseSummary> dump(ClickHouseNode server, String tableOrQuery,
312-
ClickHouseFormat format, ClickHouseCompression compression, String file) throws IOException {
313-
return dump(server, tableOrQuery, format, compression, ClickHouseUtils.getFileOutputStream(file));
308+
ClickHouseFormat format, ClickHouseCompression compression, String file) {
309+
return dump(server, tableOrQuery, ClickHouseFile.of(file, compression, 0, format));
314310
}
315311

316312
/**
@@ -403,11 +399,10 @@ static CompletableFuture<ClickHouseResponseSummary> load(ClickHouseNode server,
403399
* @return future object to get result
404400
* @throws IllegalArgumentException if any of server, table, and input is null
405401
* @throws CompletionException when error occurred during execution
406-
* @throws FileNotFoundException when file not found
407402
*/
408403
static CompletableFuture<ClickHouseResponseSummary> load(ClickHouseNode server, String table,
409-
ClickHouseFormat format, ClickHouseCompression compression, String file) throws FileNotFoundException {
410-
return load(server, table, format, compression, ClickHouseUtils.getFileInputStream(file));
404+
ClickHouseFormat format, ClickHouseCompression compression, String file) {
405+
return load(server, table, ClickHouseFile.of(file, compression, 0, format));
411406
}
412407

413408
/**

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

+11-1
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,16 @@ public static ClickHouseInputStream of(ClickHouseDeferredValue<InputStream> defe
147147
return new WrappedInputStream(null, new DeferredInputStream(deferredInput), bufferSize, postCloseAction);
148148
}
149149

150+
/**
151+
* Wraps the given file as input stream.
152+
*
153+
* @param file non-null file
154+
* @param bufferSize buffer size which is always greater than zero(usually
155+
* 8192 or larger)
156+
* @param postCloseAction custom action will be performed right after closing
157+
* the input stream
158+
* @return wrapped input
159+
*/
150160
public static ClickHouseInputStream of(ClickHouseFile file, int bufferSize, Runnable postCloseAction) {
151161
if (file == null || !file.isAvailable()) {
152162
throw new IllegalArgumentException("Non-null file required");
@@ -220,7 +230,7 @@ public static ClickHouseInputStream of(InputStream input, int bufferSize, ClickH
220230
Runnable postCloseAction) {
221231
if (input == null) {
222232
return EmptyInputStream.INSTANCE;
223-
} else if (input instanceof ClickHouseInputStream) {
233+
} else if (input != EmptyInputStream.INSTANCE && input instanceof ClickHouseInputStream) {
224234
return (ClickHouseInputStream) input;
225235
}
226236
return wrap(null, input, bufferSize, postCloseAction, compression, 0);

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

+19-5
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,17 @@ public static ClickHouseOutputStream empty() {
7070
return EmptyOutputStream.INSTANCE;
7171
}
7272

73+
/**
74+
* Wraps the given file as output stream.
75+
*
76+
* @param file non-null file
77+
* @param postCloseAction custom action will be performed right after closing
78+
* the output stream
79+
* @param bufferSize buffer size which is always greater than zero(usually
80+
* 8192
81+
* or larger)
82+
* @return wrapped output
83+
*/
7384
public static ClickHouseOutputStream of(ClickHouseFile file, int bufferSize, Runnable postCloseAction) {
7485
if (file == null || file == ClickHouseFile.NULL) {
7586
throw new IllegalArgumentException("Non-null file required");
@@ -85,7 +96,7 @@ public static ClickHouseOutputStream of(ClickHouseFile file, int bufferSize, Run
8596
/**
8697
* Wraps the given output stream.
8798
*
88-
* @param output non-null output stream
99+
* @param output output stream
89100
* @return wrapped output, or the same output if it's instance of
90101
* {@link ClickHouseOutputStream}
91102
*/
@@ -96,7 +107,7 @@ public static ClickHouseOutputStream of(OutputStream output) {
96107
/**
97108
* Wraps the given output stream.
98109
*
99-
* @param output non-null output stream
110+
* @param output output stream
100111
* @param bufferSize buffer size which is always greater than zero(usually 8192
101112
* or larger)
102113
* @return wrapped output, or the same output if it's instance of
@@ -109,7 +120,7 @@ public static ClickHouseOutputStream of(OutputStream output, int bufferSize) {
109120
/**
110121
* Wraps the given output stream.
111122
*
112-
* @param output non-null output stream
123+
* @param output output stream
113124
* @param bufferSize buffer size which is always greater than zero(usually
114125
* 8192 or larger)
115126
* @param compression compression algorithm, null or
@@ -123,8 +134,11 @@ public static ClickHouseOutputStream of(OutputStream output, int bufferSize) {
123134
public static ClickHouseOutputStream of(OutputStream output, int bufferSize, ClickHouseCompression compression,
124135
Runnable postCloseAction) {
125136
final ClickHouseOutputStream chOutput;
126-
if (compression == null || compression == ClickHouseCompression.NONE) {
127-
chOutput = output instanceof ClickHouseOutputStream ? (ClickHouseOutputStream) output
137+
if (output == null) {
138+
chOutput = EmptyOutputStream.INSTANCE;
139+
} else if (compression == null || compression == ClickHouseCompression.NONE) {
140+
chOutput = output != EmptyOutputStream.INSTANCE && output instanceof ClickHouseOutputStream
141+
? (ClickHouseOutputStream) output
128142
: new WrappedOutputStream(null, output, bufferSize, postCloseAction);
129143
} else {
130144
chOutput = wrap(null, output, bufferSize, postCloseAction, compression, 0);

0 commit comments

Comments
 (0)