Skip to content

Commit c459721

Browse files
committed
add options, simplify API and update benchmarks
1 parent b91de5c commit c459721

26 files changed

+806
-91
lines changed

CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
## 0.4.6, 2023-04-26
22
### New Features
33
* ClickHouseStatement.setMirroredOutput() for dumping ResultSet.
4+
* ClickHouseResponse.records(Class<?>) for object mapping.
5+
* Two new options(use_compilation & max_mapper_cache) reserved for future usage.
46

57
### Bug Fixes
68
* NoClassDefFoundError with clickhouse-apache-http-client-jdbc. [#1319](https://github.com/ClickHouse/clickhouse-java/issues/1319)

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

+14
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,7 @@ public static Map<ClickHouseOption, Serializable> toClientOptions(Map<?, ?> prop
204204
private final ClickHouseBufferingMode requestBuffering;
205205
private final ClickHouseBufferingMode responseBuffering;
206206
private final int maxExecutionTime;
207+
private final int maxMapperCache;
207208
private final int maxQueuedBuffers;
208209
private final int maxQueuedRequests;
209210
private final long maxResultRows;
@@ -229,6 +230,7 @@ public static Map<ClickHouseOption, Serializable> toClientOptions(Map<?, ?> prop
229230
private final boolean widenUnsignedTypes;
230231
private final boolean useBinaryString;
231232
private final boolean useBlockingQueue;
233+
private final boolean useCompilation;
232234
private final boolean useObjectsInArray;
233235
private final boolean useNoProxy;
234236
private final boolean useServerTimeZone;
@@ -312,6 +314,7 @@ public ClickHouseConfig(Map<ClickHouseOption, Serializable> options, ClickHouseC
312314
this.responseBuffering = (ClickHouseBufferingMode) getOption(ClickHouseClientOption.RESPONSE_BUFFERING,
313315
ClickHouseDefaults.BUFFERING);
314316
this.maxExecutionTime = getIntOption(ClickHouseClientOption.MAX_EXECUTION_TIME);
317+
this.maxMapperCache = getIntOption(ClickHouseClientOption.MAX_MAPPER_CACHE);
315318
this.maxQueuedBuffers = getIntOption(ClickHouseClientOption.MAX_QUEUED_BUFFERS);
316319
this.maxQueuedRequests = getIntOption(ClickHouseClientOption.MAX_QUEUED_REQUESTS);
317320
this.maxResultRows = getLongOption(ClickHouseClientOption.MAX_RESULT_ROWS);
@@ -340,6 +343,7 @@ public ClickHouseConfig(Map<ClickHouseOption, Serializable> options, ClickHouseC
340343
this.widenUnsignedTypes = getBoolOption(ClickHouseClientOption.WIDEN_UNSIGNED_TYPES);
341344
this.useBinaryString = getBoolOption(ClickHouseClientOption.USE_BINARY_STRING);
342345
this.useBlockingQueue = getBoolOption(ClickHouseClientOption.USE_BLOCKING_QUEUE);
346+
this.useCompilation = getBoolOption(ClickHouseClientOption.USE_COMPILATION);
343347
this.useObjectsInArray = getBoolOption(ClickHouseClientOption.USE_OBJECTS_IN_ARRAYS);
344348
this.useNoProxy = getBoolOption(ClickHouseClientOption.USE_NO_PROXY);
345349
this.useServerTimeZone = getBoolOption(ClickHouseClientOption.USE_SERVER_TIME_ZONE);
@@ -458,6 +462,11 @@ public int getMaxBufferSize() {
458462
return maxBufferSize;
459463
}
460464

465+
@Override
466+
public int getMaxMapperCache() {
467+
return maxMapperCache;
468+
}
469+
461470
@Override
462471
public int getBufferSize() {
463472
return bufferSize;
@@ -615,6 +624,11 @@ public boolean isUseBlockingQueue() {
615624
return useBlockingQueue;
616625
}
617626

627+
@Override
628+
public boolean isUseCompilation() {
629+
return useCompilation;
630+
}
631+
618632
@Override
619633
public boolean isUseObjectsInArray() {
620634
return useObjectsInArray;

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

+3-3
Original file line numberDiff line numberDiff line change
@@ -548,11 +548,11 @@ public List<String[]> getQueryParts() {
548548
*/
549549
public ClickHouseValue[] getParameterTemplates() {
550550
int i = 0;
551-
ClickHouseValue[] tempaltes = new ClickHouseValue[names.size()];
551+
ClickHouseValue[] templates = new ClickHouseValue[names.size()];
552552
for (ClickHouseValue v : names.values()) {
553-
tempaltes[i++] = v;
553+
templates[i++] = v;
554554
}
555-
return tempaltes;
555+
return templates;
556556
}
557557

558558
/**

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

+14
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,20 @@ default ClickHouseRecord firstRecord() {
114114
return records().iterator().next();
115115
}
116116

117+
/**
118+
* Gets the first record as mapped object. Please use {@link #records(Class)}
119+
* instead if you need to access the rest of records.
120+
*
121+
* @param <T> type of the mapped object
122+
* @param objClass non-null class of the mapped object
123+
* @return mapped object of the first record
124+
* @throws NoSuchElementException when there's no record at all
125+
* @throws UncheckedIOException when failed to read data(e.g. deserialization)
126+
*/
127+
default <T> T firstRecord(Class<T> objClass) {
128+
return records(objClass).iterator().next();
129+
}
130+
117131
/**
118132
* Returns an iterable collection of records which can be walked through in a
119133
* foreach loop. Please pay attention that: 1) {@link UncheckedIOException}

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

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@
88
import com.clickhouse.data.ClickHouseColumn;
99
import com.clickhouse.data.ClickHouseInputStream;
1010
import com.clickhouse.data.ClickHouseRecord;
11+
import com.clickhouse.data.ClickHouseRecordMapper;
1112
import com.clickhouse.data.ClickHouseRecordTransformer;
1213
import com.clickhouse.data.ClickHouseSimpleRecord;
1314
import com.clickhouse.data.ClickHouseValue;
14-
import com.clickhouse.data.mapper.IterableRecordWrapper;
1515

1616
/**
1717
* A simple response built on top of two lists: columns and records.
@@ -177,7 +177,7 @@ public <T> Iterable<T> records(Class<T> objClass) {
177177
return (Iterable<T>) records();
178178
}
179179

180-
return () -> new IterableRecordWrapper<>(columns, records().iterator(), objClass);
180+
return () -> ClickHouseRecordMapper.wrap(null, columns, records().iterator(), objClass, null);
181181
}
182182

183183
@Override

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,6 @@ public <T> Iterable<T> records(Class<T> objClass) {
150150
throw new UnsupportedOperationException(
151151
"No data processor available for deserialization, please consider to use getInputStream instead");
152152
}
153-
return processor.records(objClass);
153+
return processor.records(objClass, null);
154154
}
155155
}

clickhouse-client/src/main/java/com/clickhouse/client/config/ClickHouseClientOption.java

+11
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,11 @@ public enum ClickHouseClientOption implements ClickHouseOption {
182182
*/
183183
MAX_BUFFER_SIZE("max_buffer_size", ClickHouseDataConfig.DEFAULT_MAX_BUFFER_SIZE,
184184
"Maximum buffer size in byte can be used for streaming."),
185+
/**
186+
* Maximum number of mappers can be cached.
187+
*/
188+
MAX_MAPPER_CACHE("max_mapper_cache", ClickHouseDataConfig.DEFAULT_MAX_MAPPER_CACHE,
189+
"Maximum number of mappers can be cached."),
185190
/**
186191
* Maximum query execution time in seconds.
187192
*/
@@ -350,6 +355,12 @@ public enum ClickHouseClientOption implements ClickHouseOption {
350355
*/
351356
USE_BLOCKING_QUEUE("use_blocking_queue", ClickHouseDataConfig.DEFAULT_USE_BLOCKING_QUEUE,
352357
"Whether to use blocking queue for buffering."),
358+
/**
359+
* Whether to use compilation(generated byte code) in object mapping and
360+
* serialization.
361+
*/
362+
USE_COMPILATION("use_compilation", ClickHouseDataConfig.DEFAULT_USE_COMPILATION,
363+
"Whether to use compilation(generated byte code) in object mapping and serialization."),
353364
/**
354365
* Whether Object[] should be used instead of primitive arrays.
355366
*/

clickhouse-data/src/main/java/com/clickhouse/data/ClickHouseByteBuffer.java

+24
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
package com.clickhouse.data;
22

33
import java.io.Serializable;
4+
import java.math.BigDecimal;
45
import java.math.BigInteger;
56
import java.nio.Buffer;
67
import java.nio.ByteBuffer;
78
import java.nio.charset.Charset;
89
import java.nio.charset.StandardCharsets;
10+
import java.time.LocalDate;
11+
import java.time.LocalDateTime;
912
import java.util.Arrays;
1013
import java.util.List;
1114
import java.util.UUID;
@@ -144,6 +147,14 @@ public BigInteger asBigInteger() {
144147
return getBigInteger(0, length, false);
145148
}
146149

150+
public BigDecimal asBigDecimal() {
151+
return asBigDecimal(0);
152+
}
153+
154+
public BigDecimal asBigDecimal(int scale) {
155+
return new BigDecimal(asBigInteger(), scale);
156+
}
157+
147158
public boolean asBoolean() {
148159
return getBoolean(0);
149160
}
@@ -171,6 +182,19 @@ public double[] asDoubleArray() {
171182
return values;
172183
}
173184

185+
public LocalDate asDate() {
186+
return LocalDate.ofEpochDay(asUnsignedInteger());
187+
}
188+
189+
public LocalDateTime asDateTime() {
190+
return asDateTime(0);
191+
}
192+
193+
public LocalDateTime asDateTime(int scale) {
194+
return ClickHouseValues
195+
.convertToDateTime(asBigDecimal(ClickHouseChecker.between(scale, ClickHouseValues.PARAM_SCALE, 0, 9)));
196+
}
197+
174198
public float asFloat() {
175199
return getFloat(0);
176200
}

clickhouse-data/src/main/java/com/clickhouse/data/ClickHouseDataConfig.java

+30
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,11 @@ public ClickHouseRenameMethod getColumnRenameMethod() {
7777
return config.getColumnRenameMethod();
7878
}
7979

80+
@Override
81+
public int getMaxMapperCache() {
82+
return config.getMaxMapperCache();
83+
}
84+
8085
@Override
8186
public int getMaxQueuedBuffers() {
8287
return config.getMaxQueuedBuffers();
@@ -107,6 +112,11 @@ public boolean isUseBlockingQueue() {
107112
return config.isUseBlockingQueue();
108113
}
109114

115+
@Override
116+
public boolean isUseCompilation() {
117+
return config.isUseCompilation();
118+
}
119+
110120
@Override
111121
public boolean isUseObjectsInArray() {
112122
return config.isUseObjectsInArray();
@@ -128,6 +138,7 @@ public boolean isWidenUnsignedTypes() {
128138
static final int DEFAULT_READ_BUFFER_SIZE = DEFAULT_BUFFER_SIZE;
129139
static final int DEFAULT_WRITE_BUFFER_SIZE = DEFAULT_BUFFER_SIZE;
130140
static final int DEFAULT_MAX_BUFFER_SIZE = 128 * 1024;
141+
static final int DEFAULT_MAX_MAPPER_CACHE = 100;
131142
static final int DEFAULT_MAX_QUEUED_BUFFERS = 512;
132143
static final int DEFAULT_BUFFER_QUEUE_VARIATION = 100;
133144

@@ -138,6 +149,7 @@ public boolean isWidenUnsignedTypes() {
138149
static final boolean DEFAULT_REUSE_VALUE_WRAPPER = true;
139150
static final boolean DEFAULT_USE_BINARY_STRING = false;
140151
static final boolean DEFAULT_USE_BLOCKING_QUEUE = false;
152+
static final boolean DEFAULT_USE_COMPILATION = false;
141153
static final boolean DEFAULT_USE_OBJECT_IN_ARRAY = false;
142154
static final boolean DEFAULT_WIDEN_UNSIGNED_TYPE = false;
143155

@@ -255,6 +267,15 @@ default int getWriteBufferSize() {
255267
return DEFAULT_WRITE_BUFFER_SIZE;
256268
}
257269

270+
/**
271+
* Gets maximum number of mappers can be cached.
272+
*
273+
* @return maximum number of mappers can be cached
274+
*/
275+
default int getMaxMapperCache() {
276+
return DEFAULT_MAX_MAPPER_CACHE;
277+
}
278+
258279
/**
259280
* Gets maximum number of buffers can be queued for processing.
260281
*
@@ -328,6 +349,15 @@ default boolean isUseBlockingQueue() {
328349
return DEFAULT_USE_BLOCKING_QUEUE;
329350
}
330351

352+
/**
353+
* Checks whether compilation is used in object mapping and serialization.
354+
*
355+
* @return true if compilation is used; false otherwise
356+
*/
357+
default boolean isUseCompilation() {
358+
return DEFAULT_USE_COMPILATION;
359+
}
360+
331361
/**
332362
* Checks whether object(instead of primitive) is used in array.
333363
*

clickhouse-data/src/main/java/com/clickhouse/data/ClickHouseDataProcessor.java

+18-3
Original file line numberDiff line numberDiff line change
@@ -487,23 +487,38 @@ public final Iterable<ClickHouseRecord> records() {
487487
return () -> getInitializedSerDe().records;
488488
}
489489

490+
/**
491+
* Returns an iterable collection of mapped objects which can be walked through
492+
* in a foreach loop. Same as {@code records(objClass, null)}.
493+
*
494+
* @param <T> type of the mapped object
495+
* @param objClass non-null class of the mapped object
496+
* @return non-null iterable collection
497+
* @throws UncheckedIOException when failed to read data(e.g. deserialization)
498+
*/
499+
public final <T> Iterable<T> records(Class<T> objClass) {
500+
return records(objClass, null);
501+
}
502+
490503
/**
491504
* Returns an iterable collection of mapped objects which can be walked through
492505
* in a foreach loop. When {@code objClass} is null or {@link ClickHouseRecord},
493-
* it's same as calling {@link #records()}.
506+
* this is same as calling {@link #records()}.
494507
*
495508
* @param <T> type of the mapped object
496509
* @param objClass non-null class of the mapped object
510+
* @param template optional template object to reuse
497511
* @return non-null iterable collection
498512
* @throws UncheckedIOException when failed to read data(e.g. deserialization)
499513
*/
500514
@SuppressWarnings("unchecked")
501-
public <T> Iterable<T> records(Class<T> objClass) {
515+
public <T> Iterable<T> records(Class<T> objClass, T template) {
502516
if (objClass == null || objClass == ClickHouseRecord.class) {
503517
return (Iterable<T>) records();
504518
}
505519

506-
return () -> ClickHouseRecordMapper.wrap(getColumns(), getInitializedSerDe().records, objClass);
520+
return () -> ClickHouseRecordMapper.wrap(config, getColumns(), getInitializedSerDe().records, objClass,
521+
template);
507522
}
508523

509524
/**

clickhouse-data/src/main/java/com/clickhouse/data/ClickHouseRecordMapper.java

+9-9
Original file line numberDiff line numberDiff line change
@@ -16,28 +16,28 @@ public interface ClickHouseRecordMapper {
1616
* Wraps iterable records as mapped objects.
1717
*
1818
* @param <T> type of mapped object
19+
* @param config non-null configuration
1920
* @param columns non-null list of columns
2021
* @param records non-null iterable records
2122
* @param objClass non-null class of mapped object
23+
* @param template optional template object to reuse
2224
* @return non-null iterable objects
2325
*/
24-
static <T> Iterator<T> wrap(List<ClickHouseColumn> columns, Iterator<ClickHouseRecord> records, Class<T> objClass) {
25-
return new IterableRecordWrapper<>(columns, records, objClass);
26+
static <T> Iterator<T> wrap(ClickHouseDataConfig config, List<ClickHouseColumn> columns,
27+
Iterator<ClickHouseRecord> records, Class<T> objClass, T template) {
28+
return new IterableRecordWrapper<>(config, columns, records, objClass, template);
2629
}
2730

2831
/**
2932
* Gets mapper to turn {@link ClickHouseRecord} into user-defined object.
3033
*
34+
* @param config non-null configuration
3135
* @param columns non-null list of columns
3236
* @param objClass non-null class of the user-defined object
3337
* @return non-null user-defined object
3438
*/
35-
static ClickHouseRecordMapper of(List<ClickHouseColumn> columns, Class<?> objClass) {
36-
if (columns == null || objClass == null) {
37-
throw new IllegalArgumentException("Non-null column list and object class are required");
38-
}
39-
40-
return RecordMapperFactory.of(columns, objClass);
39+
static ClickHouseRecordMapper of(ClickHouseDataConfig config, List<ClickHouseColumn> columns, Class<?> objClass) {
40+
return RecordMapperFactory.of(config, columns, objClass);
4141
}
4242

4343
/**
@@ -59,7 +59,7 @@ default <T> T mapTo(ClickHouseRecord r, Class<T> objClass) {
5959
* @param <T> type of the user-defined object
6060
* @param r non-null record
6161
* @param objClass non-null class of the user-defined object
62-
* @param obj optional object instance to set values
62+
* @param obj reusable object instance to set values
6363
* @return non-null user-defined object, either new instance of
6464
* {@code objClass}, or same as the given {@code obj} when it's not null
6565
*/

0 commit comments

Comments
 (0)