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
116 changes: 62 additions & 54 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,86 +1,96 @@
# ClickHouse Java Client & JDBC Driver

[![clickhouse-jdbc](https://maven-badges.herokuapp.com/maven-central/ru.yandex.clickhouse/clickhouse-jdbc/badge.svg)](https://maven-badges.herokuapp.com/maven-central/ru.yandex.clickhouse/clickhouse-jdbc) ![Build Status(https://github.com/ClickHouse/clickhouse-jdbc/workflows/Build/badge.svg)](https://github.com/ClickHouse/clickhouse-jdbc/workflows/Build/badge.svg) [![Coverage](https://sonarcloud.io/api/project_badges/measure?project=ClickHouse_clickhouse-jdbc&metric=coverage)](https://sonarcloud.io/dashboard?id=ClickHouse_clickhouse-jdbc)
[![clickhouse-jdbc](https://maven-badges.herokuapp.com/maven-central/com.clickhouse/clickhouse-jdbc/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.clickhouse/clickhouse-jdbc) ![Build Status(https://github.com/ClickHouse/clickhouse-jdbc/workflows/Build/badge.svg)](https://github.com/ClickHouse/clickhouse-jdbc/workflows/Build/badge.svg) [![Coverage](https://sonarcloud.io/api/project_badges/measure?project=ClickHouse_clickhouse-jdbc&metric=coverage)](https://sonarcloud.io/dashboard?id=ClickHouse_clickhouse-jdbc)

Java client and JDBC driver for ClickHouse.
Java client and JDBC driver for ClickHouse. Java client is async and light weight library for accessing ClickHouse in Java; while JDBC driver is built on top of the Java client with more dependencies and extensions for JDBC-compliance.

## Usage

### Java Client

Use Java client when you prefer async and more "direct" way to communicate with ClickHouse. JDBC driver is actually a thin wrapper of the Java client.

```xml
<dependency>
<groupId>com.clickhouse</groupId>
<!-- you'll be able to use clickhouse-http-client and clickhouse-tcp-client as well in the near future -->
<artifactId>clickhouse-grpc-client</artifactId>
<!-- or clickhouse-grpc-client if you prefer gRPC -->
<artifactId>clickhouse-http-client</artifactId>
<version>0.3.2</version>
</dependency>
```

Example:

```Java
// declare a server to connect to
ClickHouseNode server = ClickHouseNode.of("server.domain", ClickHouseProtocol.GRPC, 9100, "my_db");

// run multiple queries in one go and wait until it's finished
ClickHouseClient.send(server,
"create database if not exists test",
"use test", // change current database from my_db to test
"create table if not exists test_table(s String) engine=Memory",
"insert into test_table values('1')('2')('3')",
"select * from test_table limit 1",
"truncate table test_table",
"drop table if exists test_table").get();

// query with named parameters
try (ClickHouseClient client = ClickHouseClient.newInstance(ClickHouseProtocol.GRPC);
ClickHouseResponse resp = client.connect(server)
.format(ClickHouseFormat.RowBinaryWithNamesAndTypes).set("send_logs_level", "trace")
.query("select id, name from some_table where id in :ids and name like :name").params(Arrays.asList(1,2,3), "%key%").execute().get()) {
// you can also use resp.stream() as well
for (ClickHouseRecord record : resp.records()) {
int id = record.getValue(0).asInteger();
String name = record.getValue(1).asString();
<details>
<summary>Expand to see example...</summary>

```Java
// declare a server to connect to
ClickHouseNode server = ClickHouseNode.of("server.domain", ClickHouseProtocol.HTTP, 8123, "my_db");

// run multiple queries in one go and wait until they're completed
ClickHouseClient.send(server, "create database if not exists test",
"use test", // change current database from my_db to test
"create table if not exists test_table(s String) engine=Memory",
"insert into test_table values('1')('2')('3')",
"select * from test_table limit 1",
"truncate table test_table",
"drop table if exists test_table").get();

// query with named parameters
try (ClickHouseClient client = ClickHouseClient.newInstance(ClickHouseProtocol.GRPC);
ClickHouseResponse resp = client.connect(server)
.format(ClickHouseFormat.RowBinaryWithNamesAndTypes).set("send_logs_level", "trace")
.query("select id, name from some_table where id in :ids and name like :name").params(Arrays.asList(1,2,3), "%key%").execute().get()) {
// you can also use resp.stream() as well
for (ClickHouseRecord record : resp.records()) {
int id = record.getValue(0).asInteger();
String name = record.getValue(1).asString();
}

ClickHouseResponseSummary summary = resp.getSummary();
long totalRows = summary.getRows();
}

ClickHouseResponseSummary summary = resp.getSummary();
long totalRows = summary.getRows();
}
// load data with custom writer
ClickHouseClient.load(server, "target_table", ClickHouseFormat.TabSeparated,
ClickHouseCompression.NONE, new ClickHouseWriter() {
@Override
public void write(OutputStream output) throws IOException {
output.write("1\t\\N\n".getBytes());
output.write("2\t123".getBytes());
}
}).get();
```
</details>

// load data with custom writer
ClickHouseClient.load(server, "target_table", ClickHouseFormat.TabSeparated,
ClickHouseCompression.NONE, new ClickHouseWriter() {
@Override
public void write(OutputStream output) throws IOException {
output.write("1\t\\N\n".getBytes());
output.write("2\t123".getBytes());
}
}).get();
```

### JDBC Driver

```xml
<dependency>
<!-- groupId and package name will be changed to com.clickhouse starting from 0.4.0 -->
<groupId>ru.yandex.clickhouse</groupId>
<!-- ru.yandex.clickhouse will be retired starting from 0.4.0 -->
<groupId>com.clickhouse</groupId>
<artifactId>clickhouse-jdbc</artifactId>
<version>0.3.2</version>
<!-- below is only needed when all you want is a shaded jar -->
<classifier>http</classifier>
<exclusions>
<exclusion>
<groupId>*</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
```

URL syntax: `jdbc:clickhouse://<host>:<port>[/<database>[?param1=value1&param2=value2]]`, e.g. `jdbc:clickhouse://localhost:8123/test?socket_timeout=120000`
URL Syntax: `jdbc:(clickhouse|ch)[:(grpc|http)]://<host>:[<port>][/<database>[?param1=value1&param2=value2]]`
- `jdbc:ch:grpc://localhost` is same as `jdbc:clickhouse:grpc://localhost:9100`
- `jdbc:ch://localhost/test?socket_timeout=120000` is same as `jdbc:clickhouse:http://localhost:8123/test?socket_timeout=120000`

JDBC Driver Class: `ru.yandex.clickhouse.ClickHouseDriver` (will be changed to `com.clickhouse.jdbc.ClickHouseDriver` starting from 0.4.0)
JDBC Driver Class: `com.clickhouse.jdbc.ClickHouseDriver` (will remove `ru.yandex.clickhouse.ClickHouseDriver` starting from 0.4.0)

For example:

```java
String url = "jdbc:clickhouse://localhost:8123/test";
ClickHouseProperties properties = new ClickHouseProperties();
String url = "jdbc:ch://localhost/test";
Properties properties = new Properties();
// set connection options - see more defined in ClickHouseConnectionSettings
properties.setClientName("Agent #1");
...
Expand All @@ -96,13 +106,11 @@ additionalDBParams.put(ClickHouseQueryParam.SESSION_ID, "new-session-id");
...
try (ClickHouseConnection conn = dataSource.getConnection();
ClickHouseStatement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(sql, additionalDBParams)) {
ResultSet rs = stmt.executeQuery(sql)) {
...
}
```

Additionally, if you have a few instances, you can use `BalancedClickhouseDataSource`.

### Extended API

In order to provide non-JDBC complaint data manipulation functionality, proprietary API exists.
Expand Down Expand Up @@ -174,7 +182,7 @@ Java 8 or higher is required in order to use Java client and/or JDBC driver.
| \*String | Y | Y | |
| UUID | Y | Y | |
| AggregatedFunction | N | N | Partially supported |
| Array | Y | N | |
| Array | Y | Y | |
| Map | Y | Y | |
| Nested | Y | N | |
| Tuple | Y | N | |
Expand Down
4 changes: 2 additions & 2 deletions clickhouse-benchmark/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

<properties>
<clickhouse4j-driver.version>1.4.4</clickhouse4j-driver.version>
<native-driver.version>2.6.0</native-driver.version>
<native-driver.version>2.6.1</native-driver.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<jmh.version>1.33</jmh.version>
<shade.name>benchmarks</shade.name>
Expand Down Expand Up @@ -138,7 +138,7 @@
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>module-info.class</exclude>
<exclude>**/module-info.class</exclude>
<exclude>META-INF/MANIFEST.MF</exclude>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@

@FunctionalInterface
public interface ConsumeValueFunction {
void consume(Blackhole blackhole, ResultSet rs, int columnIndex) throws SQLException;
void consume(Blackhole blackhole, ResultSet rs, int rowIndex, int columnIndex) throws SQLException;
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import com.clickhouse.benchmark.BaseState;
import com.clickhouse.benchmark.Constants;
import com.clickhouse.benchmark.ServerState;
// import com.github.housepower.settings.ClickHouseDefines;

@State(Scope.Thread)
public class DriverState extends BaseState {
Expand Down Expand Up @@ -49,6 +50,8 @@ public void doSetup(ServerState serverState) throws Exception {
url = String.format(jdbcDriver.getUrlTemplate(), serverState.getHost(),
serverState.getPort(jdbcDriver.getDefaultPort()), serverState.getDatabase(), serverState.getUser(),
serverState.getPassword(), compression);
// ClickHouseDefines.WRITE_COMPRESS = false;
// ClickHouseDefines.READ_DECOMPRESS = Boolean.parseBoolean(compression);
conn = driver.connect(url, new Properties());

try (Statement s = conn.createStatement()) {
Expand Down Expand Up @@ -126,11 +129,11 @@ public boolean usePreparedStatement() {

public ConsumeValueFunction getConsumeFunction(ConsumeValueFunction defaultFunc) {
if ("string".equals(type)) {
return (b, r, i) -> b.consume(r.getString(i));
return (b, r, l, i) -> b.consume(r.getString(i));
} else if ("object".equals(type)) {
return (b, r, i) -> b.consume(r.getObject(i));
return (b, r, l, i) -> b.consume(r.getObject(i));
} else if (defaultFunc == null) {
return (b, r, i) -> b.consume(i);
return (b, r, l, i) -> b.consume(i);
} else {
return defaultFunc;
}
Expand Down
Loading