Skip to content

Commit 999766b

Browse files
authored
Merge pull request #388 from yandex/statement-refactor
Statement refactor
2 parents 3354de1 + f29f079 commit 999766b

File tree

12 files changed

+606
-59
lines changed

12 files changed

+606
-59
lines changed

README.md

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,48 @@ JDBC Driver Class:
2222

2323
additionally, if you have a few instances, you can use `BalancedClickhouseDataSource`.
2424

25+
26+
### Extended API
27+
In order to provide non-JDBC complaint data manipulation functionality, proprietary API exists.
28+
Entry point for API is `ClickHouseStatement#write()` method.
29+
30+
#### Importing file into table
31+
```java
32+
import ru.yandex.clickhouse.ClickHouseStatement;
33+
ClickHouseStatement sth = connection.createStatement();
34+
sth
35+
.write() // Write API entrypoint
36+
.table("default.my_table") // where to write data
37+
.option("format_csv_delimiter", ";") // specific param
38+
.data(new File("/path/to/file.csv"), ClickHouseFormat.CSV) // specify input
39+
.send();
40+
```
41+
#### Configurable send
42+
```java
43+
import ru.yandex.clickhouse.ClickHouseStatement;
44+
ClickHouseStatement sth = connection.createStatement();
45+
sth
46+
.write()
47+
.sql("INSERT INTO default.my_table (a,b,c) VALUES")
48+
.data(new MyCustomInputStream(), ClickHouseFormat.JSONEachRow)
49+
.addDbParam(ClickHouseQueryParam.MAX_PARALLEL_REPLICAS, 2)
50+
.send();
51+
```
52+
#### Send data in binary formatd with custom user callback
53+
```java
54+
import ru.yandex.clickhouse.ClickHouseStatement;
55+
ClickHouseStatement sth = connection.createStatement();
56+
sth.write().send("INSERT INTO test.writer", new ClickHouseStreamCallback() {
57+
@Override
58+
public void writeTo(ClickHouseRowBinaryStream stream) throws IOException {
59+
for (int i = 0; i < 10; i++) {
60+
stream.writeInt32(i);
61+
stream.writeString("Name " + i);
62+
}
63+
}
64+
},
65+
ClickHouseFormat.RowBinary); // RowBinary or Native are supported
66+
```
2567
### Compiling with maven
2668
The driver is built with maven.
2769
`mvn package -DskipTests=true`

pom.xml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
<groupId>ru.yandex.clickhouse</groupId>
66
<artifactId>clickhouse-jdbc</artifactId>
7-
<version>0.1-SNAPSHOT</version>
7+
<version>${project.version}</version>
88
<packaging>jar</packaging>
99

1010
<name>clickhouse-jdbc</name>
@@ -39,10 +39,16 @@
3939
<name>Yuriy Galitskiy</name>
4040
<email>[email protected]</email>
4141
</developer>
42+
<developer>
43+
<id>krash</id>
44+
<name>Alexandr Krasheninnikov</name>
45+
<email>[email protected]</email>
46+
</developer>
4247
</developers>
4348

4449
<properties>
4550
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
51+
<project.version>0.1.55</project.version>
4652
</properties>
4753

4854
<dependencies>

src/main/java/ru/yandex/clickhouse/ClickHouseStatement.java

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515

1616
public interface ClickHouseStatement extends Statement {
17+
1718
ClickHouseResponse executeQueryClickhouseResponse(String sql) throws SQLException;
1819

1920
ClickHouseResponse executeQueryClickhouseResponse(String sql, Map<ClickHouseQueryParam, String> additionalDBParams) throws SQLException;
@@ -40,24 +41,68 @@ ResultSet executeQuery(String sql,
4041
List<ClickHouseExternalData> externalData,
4142
Map<String, String> additionalRequestParams) throws SQLException;
4243

44+
/**
45+
* @see #write()
46+
*/
47+
@Deprecated
4348
void sendStream(InputStream content, String table, Map<ClickHouseQueryParam, String> additionalDBParams) throws SQLException;
4449

50+
/**
51+
* @see #write()
52+
*/
53+
@Deprecated
4554
void sendStream(InputStream content, String table) throws SQLException;
4655

56+
/**
57+
* @see #write()
58+
*/
59+
@Deprecated
4760
void sendRowBinaryStream(String sql, Map<ClickHouseQueryParam, String> additionalDBParams, ClickHouseStreamCallback callback) throws SQLException;
4861

62+
/**
63+
* @see #write()
64+
*/
65+
@Deprecated
4966
void sendRowBinaryStream(String sql, ClickHouseStreamCallback callback) throws SQLException;
5067

68+
/**
69+
* @see #write()
70+
*/
71+
@Deprecated
5172
void sendNativeStream(String sql, Map<ClickHouseQueryParam, String> additionalDBParams, ClickHouseStreamCallback callback) throws SQLException;
52-
73+
74+
/**
75+
* @see #write()
76+
*/
77+
@Deprecated
5378
void sendNativeStream(String sql, ClickHouseStreamCallback callback) throws SQLException;
5479

80+
/**
81+
* @see #write()
82+
*/
83+
@Deprecated
5584
void sendCSVStream(InputStream content, String table, Map<ClickHouseQueryParam, String> additionalDBParams) throws SQLException;
5685

86+
/**
87+
* @see #write()
88+
*/
89+
@Deprecated
5790
void sendCSVStream(InputStream content, String table) throws SQLException;
5891

92+
/**
93+
* @see #write()
94+
*/
95+
@Deprecated
5996
void sendStreamSQL(InputStream content, String sql, Map<ClickHouseQueryParam, String> additionalDBParams) throws SQLException;
6097

98+
/**
99+
* @see #write()
100+
*/
101+
@Deprecated
61102
void sendStreamSQL(InputStream content, String sql) throws SQLException;
62103

104+
/**
105+
* Returns extended write-API
106+
*/
107+
Writer write();
63108
}

src/main/java/ru/yandex/clickhouse/ClickHouseStatementImpl.java

Lines changed: 61 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,42 @@
11
package ru.yandex.clickhouse;
22

3-
import java.io.ByteArrayInputStream;
4-
import java.io.IOException;
5-
import java.io.InputStream;
6-
import java.net.HttpURLConnection;
7-
import java.net.URI;
8-
import java.net.URISyntaxException;
9-
import java.sql.ResultSet;
10-
import java.sql.SQLException;
11-
import java.sql.SQLWarning;
12-
import java.util.ArrayList;
13-
import java.util.EnumMap;
14-
import java.util.List;
15-
import java.util.Map;
16-
import java.util.TimeZone;
17-
import java.util.UUID;
18-
3+
import com.google.common.base.Strings;
194
import org.apache.http.HttpEntity;
205
import org.apache.http.HttpResponse;
216
import org.apache.http.NameValuePair;
227
import org.apache.http.client.methods.HttpGet;
238
import org.apache.http.client.methods.HttpPost;
249
import org.apache.http.client.utils.URIBuilder;
2510
import org.apache.http.entity.ContentType;
26-
import org.apache.http.entity.InputStreamEntity;
2711
import org.apache.http.entity.StringEntity;
2812
import org.apache.http.entity.mime.MultipartEntityBuilder;
2913
import org.apache.http.impl.client.CloseableHttpClient;
3014
import org.apache.http.message.BasicNameValuePair;
3115
import org.apache.http.util.EntityUtils;
3216
import org.slf4j.Logger;
3317
import org.slf4j.LoggerFactory;
34-
35-
import com.google.common.base.Strings;
36-
3718
import ru.yandex.clickhouse.domain.ClickHouseFormat;
3819
import ru.yandex.clickhouse.except.ClickHouseException;
3920
import ru.yandex.clickhouse.except.ClickHouseExceptionSpecifier;
40-
import ru.yandex.clickhouse.response.ClickHouseLZ4Stream;
41-
import ru.yandex.clickhouse.response.ClickHouseResponse;
42-
import ru.yandex.clickhouse.response.ClickHouseResultSet;
43-
import ru.yandex.clickhouse.response.ClickHouseScrollableResultSet;
44-
import ru.yandex.clickhouse.response.FastByteArrayOutputStream;
21+
import ru.yandex.clickhouse.response.*;
4522
import ru.yandex.clickhouse.settings.ClickHouseProperties;
4623
import ru.yandex.clickhouse.settings.ClickHouseQueryParam;
4724
import ru.yandex.clickhouse.util.ClickHouseRowBinaryInputStream;
4825
import ru.yandex.clickhouse.util.ClickHouseStreamCallback;
49-
import ru.yandex.clickhouse.util.ClickHouseStreamHttpEntity;
5026
import ru.yandex.clickhouse.util.Utils;
5127
import ru.yandex.clickhouse.util.guava.StreamUtils;
5228

29+
import java.io.ByteArrayInputStream;
30+
import java.io.IOException;
31+
import java.io.InputStream;
32+
import java.net.HttpURLConnection;
33+
import java.net.URI;
34+
import java.net.URISyntaxException;
35+
import java.sql.ResultSet;
36+
import java.sql.SQLException;
37+
import java.sql.SQLWarning;
38+
import java.util.*;
39+
5340

5441
public class ClickHouseStatementImpl implements ClickHouseStatement {
5542

@@ -616,9 +603,7 @@ private InputStream getInputStream(
616603
requestEntity = entityBuilder.build();
617604
}
618605

619-
if (properties.isDecompress()) {
620-
requestEntity = new LZ4EntityWrapper(requestEntity, properties.getMaxCompressBufferSize());
621-
}
606+
requestEntity = applyRequestBodyCompression(requestEntity);
622607

623608
HttpEntity entity = null;
624609
try {
@@ -775,9 +760,8 @@ public void sendRowBinaryStream(String sql, ClickHouseStreamCallback callback) t
775760

776761
@Override
777762
public void sendRowBinaryStream(String sql, Map<ClickHouseQueryParam, String> additionalDBParams, ClickHouseStreamCallback callback) throws SQLException {
778-
sendStream(
779-
new ClickHouseStreamHttpEntity(callback, getConnection().getTimeZone(), properties), sql, ClickHouseFormat.RowBinary, additionalDBParams
780-
);
763+
write().withDbParams(additionalDBParams)
764+
.send(sql, callback, ClickHouseFormat.RowBinary);
781765
}
782766

783767
@Override
@@ -787,73 +771,81 @@ public void sendNativeStream(String sql, ClickHouseStreamCallback callback) thro
787771

788772
@Override
789773
public void sendNativeStream(String sql, Map<ClickHouseQueryParam, String> additionalDBParams, ClickHouseStreamCallback callback) throws SQLException {
790-
sendStream(
791-
new ClickHouseStreamHttpEntity(callback, getConnection().getTimeZone(), properties), sql, ClickHouseFormat.Native, additionalDBParams
792-
);
774+
write().withDbParams(additionalDBParams)
775+
.send(sql, callback, ClickHouseFormat.Native);
793776
}
794777

795778
@Override
796-
public void sendCSVStream(InputStream content, String table, Map<ClickHouseQueryParam, String> additionalDBParams) throws ClickHouseException {
797-
String query = "INSERT INTO " + table;
798-
sendStream(new InputStreamEntity(content, -1), query, ClickHouseFormat.CSV, additionalDBParams);
779+
public void sendCSVStream(InputStream content, String table, Map<ClickHouseQueryParam, String> additionalDBParams) throws SQLException {
780+
write()
781+
.table(table)
782+
.withDbParams(additionalDBParams)
783+
.data(content)
784+
.format(ClickHouseFormat.CSV)
785+
.send();
799786
}
800787

801788
@Override
802-
public void sendCSVStream(InputStream content, String table) throws ClickHouseException {
789+
public void sendCSVStream(InputStream content, String table) throws SQLException {
803790
sendCSVStream(content, table, null);
804791
}
805792

806793
@Override
807-
public void sendStream(InputStream content, String table) throws ClickHouseException {
794+
public void sendStream(InputStream content, String table) throws SQLException {
808795
sendStream(content, table, null);
809796
}
810797

811798
@Override
812799
public void sendStream(InputStream content, String table,
813-
Map<ClickHouseQueryParam, String> additionalDBParams) throws ClickHouseException {
814-
String query = "INSERT INTO " + table;
815-
sendStream(new InputStreamEntity(content, -1), query, ClickHouseFormat.TabSeparated, additionalDBParams);
800+
Map<ClickHouseQueryParam, String> additionalDBParams) throws SQLException {
801+
write()
802+
.table(table)
803+
.data(content)
804+
.withDbParams(additionalDBParams)
805+
.format(ClickHouseFormat.TabSeparated)
806+
.send();
816807
}
817808

809+
@Deprecated
818810
public void sendStream(HttpEntity content, String sql) throws ClickHouseException {
819811
sendStream(content, sql, ClickHouseFormat.TabSeparated, null);
820812
}
821813

814+
@Deprecated
822815
public void sendStream(HttpEntity content, String sql,
823816
Map<ClickHouseQueryParam, String> additionalDBParams) throws ClickHouseException {
824817
sendStream(content, sql, ClickHouseFormat.TabSeparated, additionalDBParams);
825818
}
826819

827820
private void sendStream(HttpEntity content, String sql, ClickHouseFormat format,
828821
Map<ClickHouseQueryParam, String> additionalDBParams) throws ClickHouseException {
829-
sendStreamSQL(content, sql + " FORMAT " + format.name(), additionalDBParams);
822+
823+
Writer writer = write().format(format).withDbParams(additionalDBParams).sql(sql);
824+
sendStream(writer, content);
830825
}
831826

832827
@Override
833828
public void sendStreamSQL(InputStream content, String sql,
834-
Map<ClickHouseQueryParam, String> additionalDBParams) throws ClickHouseException {
835-
sendStreamSQL(new InputStreamEntity(content, -1), sql, additionalDBParams);
829+
Map<ClickHouseQueryParam, String> additionalDBParams) throws SQLException {
830+
write().data(content).sql(sql).withDbParams(additionalDBParams).send();
836831
}
837832

838833
@Override
839-
public void sendStreamSQL(InputStream content, String sql) throws ClickHouseException {
840-
sendStreamSQL(new InputStreamEntity(content, -1), sql, null);
834+
public void sendStreamSQL(InputStream content, String sql) throws SQLException {
835+
write().sql(sql).data(content).send();
841836
}
842837

843-
private void sendStreamSQL(HttpEntity content, String sql,
844-
Map<ClickHouseQueryParam, String> additionalDBParams) throws ClickHouseException {
845-
// echo -ne '10\n11\n12\n' | POST 'http://localhost:8123/?query=INSERT INTO t FORMAT TabSeparated'
838+
void sendStream(Writer writer, HttpEntity content) throws ClickHouseException {
846839
HttpEntity entity = null;
847840
try {
848-
URI uri = buildRequestUri(null, null, additionalDBParams, null, false);
841+
842+
URI uri = buildRequestUri(writer.getSql(), null, writer.getAdditionalDBParams(), writer.getRequestParams(), false);
849843
uri = followRedirects(uri);
850-
HttpEntity requestEntity = new BodyEntityWrapper(sql, content);
844+
845+
content = applyRequestBodyCompression(content);
851846

852847
HttpPost httpPost = new HttpPost(uri);
853-
if (properties.isDecompress()) {
854-
requestEntity = new LZ4EntityWrapper(requestEntity, properties.getMaxCompressBufferSize());
855-
}
856-
httpPost.setEntity(requestEntity);
848+
httpPost.setEntity(content);
857849
HttpResponse response = client.execute(httpPost);
858850
entity = response.getEntity();
859851
checkForErrorAndThrow(entity, response);
@@ -892,6 +884,13 @@ public boolean isCloseOnCompletion() throws SQLException {
892884
return closeOnCompletion;
893885
}
894886

887+
private HttpEntity applyRequestBodyCompression(final HttpEntity entity) {
888+
if (properties.isDecompress()) {
889+
return new LZ4EntityWrapper(entity, properties.getMaxCompressBufferSize());
890+
}
891+
return entity;
892+
}
893+
895894
private ClickHouseResultSet createResultSet(InputStream is, int bufferSize, String db, String table, boolean usesWithTotals,
896895
ClickHouseStatement statement, TimeZone timezone, ClickHouseProperties properties) throws IOException {
897896
if(isResultSetScrollable) {
@@ -916,4 +915,9 @@ private Map<ClickHouseQueryParam, String> addQueryIdTo(Map<ClickHouseQueryParam,
916915

917916
return parameters;
918917
}
918+
919+
@Override
920+
public Writer write() {
921+
return new Writer(this);
922+
}
919923
}

0 commit comments

Comments
 (0)