1
1
package com .clickhouse .client ;
2
2
3
+ import java .io .IOException ;
3
4
import java .io .InputStream ;
4
5
import java .io .OutputStream ;
5
6
import java .io .Serializable ;
7
+ import java .io .UncheckedIOException ;
6
8
import java .util .ArrayList ;
7
9
import java .util .Collection ;
8
10
import java .util .Collections ;
14
16
import java .util .Map ;
15
17
import java .util .Objects ;
16
18
import java .util .Map .Entry ;
19
+ import java .util .concurrent .CancellationException ;
17
20
import java .util .concurrent .CompletableFuture ;
18
21
import java .util .concurrent .CompletionException ;
22
+ import java .util .concurrent .ExecutionException ;
19
23
import java .util .concurrent .atomic .AtomicReference ;
20
24
import java .util .Optional ;
21
25
import java .util .Properties ;
@@ -39,6 +43,8 @@ public class ClickHouseRequest<SelfT extends ClickHouseRequest<SelfT>> implement
39
43
* Mutation request.
40
44
*/
41
45
public static class Mutation extends ClickHouseRequest <Mutation > {
46
+ private ClickHouseWriter writer ;
47
+
42
48
protected Mutation (ClickHouseRequest <?> request , boolean sealed ) {
43
49
super (request .getClient (), request .server , request .serverRef , request .options , sealed );
44
50
this .settings .putAll (request .settings );
@@ -105,6 +111,20 @@ public Mutation format(ClickHouseFormat format) {
105
111
return super .format (format );
106
112
}
107
113
114
+ /**
115
+ * Sets custom writer for streaming. This will create a piped stream between the
116
+ * writer and ClickHouse server.
117
+ *
118
+ * @param writer writer
119
+ * @return mutation request
120
+ */
121
+ public Mutation data (ClickHouseWriter writer ) {
122
+ checkSealed ();
123
+
124
+ this .writer = changeProperty (PROP_WRITER , this .writer , writer );
125
+ return this ;
126
+ }
127
+
108
128
/**
109
129
* Loads data from given file which may or may not be compressed.
110
130
*
@@ -197,6 +217,70 @@ public Mutation data(ClickHouseDeferredValue<ClickHouseInputStream> input) {
197
217
return this ;
198
218
}
199
219
220
+ @ Override
221
+ public CompletableFuture <ClickHouseResponse > execute () {
222
+ if (writer != null ) {
223
+ ClickHouseConfig c = getConfig ();
224
+ ClickHousePipedOutputStream stream = ClickHouseDataStreamFactory .getInstance ()
225
+ .createPipedOutputStream (c , null );
226
+ data (stream .getInputStream ());
227
+ CompletableFuture <ClickHouseResponse > future = null ;
228
+ if (c .isAsync ()) {
229
+ future = getClient ().execute (isSealed () ? this : seal ());
230
+ }
231
+ try (ClickHouseOutputStream out = stream ) {
232
+ writer .write (out );
233
+ } catch (IOException e ) {
234
+ throw new CompletionException (e );
235
+ }
236
+ if (future != null ) {
237
+ return future ;
238
+ }
239
+ }
240
+
241
+ return getClient ().execute (isSealed () ? this : seal ());
242
+ }
243
+
244
+ @ Override
245
+ public ClickHouseResponse executeAndWait () throws ClickHouseException {
246
+ if (writer != null ) {
247
+ ClickHouseConfig c = getConfig ();
248
+ ClickHousePipedOutputStream stream = ClickHouseDataStreamFactory .getInstance ()
249
+ .createPipedOutputStream (c , null );
250
+ data (stream .getInputStream ());
251
+ CompletableFuture <ClickHouseResponse > future = null ;
252
+ if (c .isAsync ()) {
253
+ future = getClient ().execute (isSealed () ? this : seal ());
254
+ }
255
+ try (ClickHouseOutputStream out = stream ) {
256
+ writer .write (out );
257
+ } catch (IOException e ) {
258
+ throw ClickHouseException .of (e , getServer ());
259
+ }
260
+ if (future != null ) {
261
+ try {
262
+ return future .get ();
263
+ } catch (InterruptedException e ) {
264
+ Thread .currentThread ().interrupt ();
265
+ throw ClickHouseException .forCancellation (e , getServer ());
266
+ } catch (CancellationException e ) {
267
+ throw ClickHouseException .forCancellation (e , getServer ());
268
+ } catch (ExecutionException | UncheckedIOException e ) {
269
+ Throwable cause = e .getCause ();
270
+ if (cause == null ) {
271
+ cause = e ;
272
+ }
273
+ throw cause instanceof ClickHouseException ? (ClickHouseException ) cause
274
+ : ClickHouseException .of (cause , getServer ());
275
+ } catch (RuntimeException e ) { // unexpected
276
+ throw ClickHouseException .of (e , getServer ());
277
+ }
278
+ }
279
+ }
280
+
281
+ return getClient ().executeAndWait (isSealed () ? this : seal ());
282
+ }
283
+
200
284
/**
201
285
* Sends mutation requets for execution. Same as
202
286
* {@code client.execute(request.seal())}.
@@ -256,6 +340,7 @@ public Mutation seal() {
256
340
static final String PROP_PREPARED_QUERY = "preparedQuery" ;
257
341
static final String PROP_QUERY = "query" ;
258
342
static final String PROP_QUERY_ID = "queryId" ;
343
+ static final String PROP_WRITER = "writer" ;
259
344
260
345
private final boolean sealed ;
261
346
0 commit comments