-
Notifications
You must be signed in to change notification settings - Fork 530
/
ClickHouseClientOption.java
622 lines (594 loc) · 26 KB
/
ClickHouseClientOption.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
package com.clickhouse.client.config;
import java.io.Serializable;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import com.clickhouse.config.ClickHouseOption;
import com.clickhouse.data.ClickHouseChecker;
import com.clickhouse.data.ClickHouseCompression;
import com.clickhouse.data.ClickHouseDataConfig;
/**
* Generic client options.
*/
public enum ClickHouseClientOption implements ClickHouseOption {
/**
* Whether the client should run in async mode(e.g.
* {@link com.clickhouse.client.ClickHouseClient#execute(com.clickhouse.client.ClickHouseRequest)}
* in a separate thread).
*/
ASYNC("async", ClickHouseDataConfig.DEFAULT_ASYNC, "Whether the client should run in async mode."),
/**
* Whether the client should discover more nodes from system tables and/or
* clickhouse-keeper/zookeeper.
*/
AUTO_DISCOVERY("auto_discovery", false,
"Whether the client should discover more nodes from system tables and/or clickhouse-keeper/zookeeper."),
/**
* Custom server settings for all queries.
*/
CUSTOM_SETTINGS("custom_settings", "", "Comma separated custom server settings for all queries."),
/**
* Custom socket factory.
*/
CUSTOM_SOCKET_FACTORY("custom_socket_factory", "",
"Full qualified class name of custom socket factory. This is only supported by TCP client and Apache Http Client."),
/**
* Additional socket factory options. Only useful only when
* {@link #CUSTOM_SOCKET_FACTORY} is set.
*/
CUSTOM_SOCKET_FACTORY_OPTIONS("custom_socket_factory_options", "",
"Comma separated options for custom socket factory."),
/**
* Load balancing policy.
*/
LOAD_BALANCING_POLICY("load_balancing_policy", "",
"Load balancing policy, can be one of '', 'firstAlive', 'random', 'roundRobin', or full qualified class name implementing ClickHouseLoadBalancingPolicy."),
/**
* Load balancing tags for filtering out nodes.
*/
LOAD_BALANCING_TAGS("load_balancing_tags", "", "Load balancing tags for filtering out nodes."),
/**
* Health check interval in milliseconds.
*/
HEALTH_CHECK_INTERVAL("health_check_interval", 0,
"Health check interval in milliseconds, zero or negative value means one-time."),
/**
* Health check method.
*/
HEALTH_CHECK_METHOD("health_check_method", ClickHouseHealthCheckMethod.SELECT_ONE, "Health check method."),
/**
* Node discovery interval in milliseconds.
*/
NODE_DISCOVERY_INTERVAL("node_discovery_interval", 0,
"Node discovery interval in milliseconds, zero or negative value means one-time discovery."),
/**
* Maximum number of nodes can be discovered at a time.
*/
NODE_DISCOVERY_LIMIT("node_discovery_limit", 100,
"Maximum number of nodes can be discovered at a time, zero or negative value means no limit."),
/**
* Node check interval in milliseconds.
*/
NODE_CHECK_INTERVAL("node_check_interval", 0,
"Node check interval in milliseconds, negative number is treated as zero."),
/**
* Maximum number of nodes can be used for operation at a time.
*/
NODE_GROUP_SIZE("node_group_size", 50,
"Maximum number of nodes can be used for operation at a time, zero or negative value means all."),
/**
* Whether to perform health check against all nodes or just faulty ones.
*/
CHECK_ALL_NODES("check_all_nodes", false,
"Whether to perform health check against all nodes or just faulty ones."),
/**
* Default buffer size in byte for both request and response. It will be reset
* to {@link #MAX_BUFFER_SIZE} if it's too large.
*/
BUFFER_SIZE("buffer_size", ClickHouseDataConfig.DEFAULT_BUFFER_SIZE,
"Default buffer size in byte for both request and response."),
/**
* Number of times the buffer queue is filled up before increasing capacity of
* buffer queue. Zero or negative value means the queue length is fixed.
*/
BUFFER_QUEUE_VARIATION("buffer_queue_variation", ClickHouseDataConfig.DEFAULT_BUFFER_QUEUE_VARIATION,
"Number of times the buffer queue is filled up before increasing capacity of buffer queue. Zero or negative value means the queue length is fixed."),
/**
* Read buffer size in byte. It's mainly for input stream(e.g. reading data from
* server response). Its value defaults to {@link #BUFFER_SIZE}, and it will be
* reset to {@link #MAX_BUFFER_SIZE} when it's too large.
*/
READ_BUFFER_SIZE("read_buffer_size", 0,
"Read buffer size in byte, zero or negative value means same as buffer_size"),
/**
* Write buffer size in byte. It's mainly for output stream(e.g. writing data
* into request). Its value defaults to {@link #BUFFER_SIZE}, and it will
* be reset to {@link #MAX_BUFFER_SIZE} when it's too large.
*/
WRITE_BUFFER_SIZE("write_buffer_size", 0,
"Write buffer size in byte, zero or negative value means same as buffer_size"),
/**
* Maximum request chunk size in byte.
*/
REQUEST_CHUNK_SIZE("request_chunk_size", 0,
"Maximum request chunk size in byte, zero or negative value means same as write_buffer_size"),
/**
* Request buffering mode.
*/
REQUEST_BUFFERING("request_buffering", ClickHouseDefaults.BUFFERING.getDefaultValue(),
"Request buffering mode"),
/**
* Response buffering mode.
*/
RESPONSE_BUFFERING("response_buffering", ClickHouseDefaults.BUFFERING.getDefaultValue(),
"Response buffering mode."),
/**
* Client name.
*/
CLIENT_NAME("client_name", "ClickHouse Java Client",
"Client name, which is either 'client_name' or 'http_user_agent' shows up in system.query_log table."),
/**
* Whether server will compress response to client or not.
*/
COMPRESS("compress", true, "Whether the server will compress response it sends to client."),
/**
* Whether server will decompress request from client or not.
*/
DECOMPRESS("decompress", false, "Whether the server will decompress request from client."),
/**
* Compression algorithm server will use to compress response, when
* {@link #COMPRESS} is {@code true}.
*/
COMPRESS_ALGORITHM("compress_algorithm", ClickHouseCompression.LZ4,
"Algorithm used for server to compress response."),
/**
* Compression algorithm server will use to decompress request, when
* {@link #DECOMPRESS} is {@code true}.
*/
DECOMPRESS_ALGORITHM("decompress_algorithm", ClickHouseCompression.LZ4,
"Algorithm for server to decompress request."),
/**
* Compression level for compressing server response.
*/
COMPRESS_LEVEL("compress_level", ClickHouseDataConfig.DEFAULT_READ_COMPRESS_LEVEL,
"Compression level for response, -1 standards for default"),
/**
* Compression level for decompress client request.
*/
DECOMPRESS_LEVEL("decompress_level", ClickHouseDataConfig.DEFAULT_WRITE_COMPRESS_LEVEL,
"Compression level for request, -1 standards for default"),
/**
* Connection timeout in milliseconds.
*/
CONNECTION_TIMEOUT("connect_timeout", 5000,
"Connection timeout in milliseconds. It's also used for waiting a connection being closed."),
/**
* Default database.
*/
DATABASE("database", "", "Default database."),
/**
* Maximum number of times failover can happen for a request.
*/
FAILOVER("failover", 0,
"Maximum number of times failover can happen for a request, zero or negative value means no failover."),
/**
* Default format.
*/
FORMAT("format", ClickHouseDataConfig.DEFAULT_FORMAT, "Default format."),
/**
* Whether to log leading comment(as log_comment in system.query_log) of the
* query.
*/
LOG_LEADING_COMMENT("log_leading_comment", false,
"Whether to log leading comment(as log_comment in system.query_log) of the query."),
/**
* Maximum buffer size in byte can be used for streaming. It's not supposed to
* be larger than {@code Integer.MAX_VALUE - 8}.
*/
MAX_BUFFER_SIZE("max_buffer_size", ClickHouseDataConfig.DEFAULT_MAX_BUFFER_SIZE,
"Maximum buffer size in byte can be used for streaming."),
/**
* Maximum number of mappers can be cached.
*/
MAX_MAPPER_CACHE("max_mapper_cache", ClickHouseDataConfig.DEFAULT_MAX_MAPPER_CACHE,
"Maximum number of mappers can be cached."),
/**
* Maximum query execution time in seconds.
*/
MAX_EXECUTION_TIME("max_execution_time", 0, "Maximum query execution time in seconds, 0 means no limit."),
/**
* Maximum queued in-memory buffers.
*/
MAX_QUEUED_BUFFERS("max_queued_buffers", ClickHouseDataConfig.DEFAULT_MAX_QUEUED_BUFFERS,
"Maximum queued in-memory buffers, 0 or negative number means no limit."),
/**
* Maxium queued requests. When {@link #MAX_THREADS_PER_CLIENT} is greater than
* zero, this will also be applied to client's thread pool as well.
*/
MAX_QUEUED_REQUESTS("max_queued_requests", 0, "Maximum queued requests, 0 or negative number means no limit."),
/**
* Maximum rows allowed in the result.
*/
MAX_RESULT_ROWS("max_result_rows", 0L,
"Limit on the number of rows in the result. "
+ "Also checked for subqueries, and on remote servers when running parts of a distributed query."),
/**
* Maximum size of thread pool for each client.
*/
MAX_THREADS_PER_CLIENT("max_threads_per_client", 0,
"Size of thread pool for each client instance, 0 or negative number means the client will use shared thread pool."),
/**
* Product name usered in user agent.
*/
PRODUCT_NAME("product_name", "ClickHouse-JavaClient", "Product name used in user agent."),
/**
* Method to rename response columns.
*/
RENAME_RESPONSE_COLUMN("rename_response_column", ClickHouseDataConfig.DEFAULT_COLUMN_RENAME_METHOD,
"Method to rename response columns."),
/**
* Maximum number of times retry can happen for a request.
*/
RETRY("retry", 0,
"Maximum number of times retry can happen for a request, zero or negative value means no retry."),
/**
* Whether to repeat execution when session is locked, until timed out(according
* to {@link #SESSION_TIMEOUT} or {@link #CONNECTION_TIMEOUT}).
*/
REPEAT_ON_SESSION_LOCK("repeat_on_session_lock", true,
"Whether to repeat execution when session is locked, until timed out(according to 'session_timeout' or 'connect_timeout')."),
/**
* Whether to reuse wrapper of value(e.g. ClickHouseValue or
* ClickHouseRecord) for memory efficiency.
*/
REUSE_VALUE_WRAPPER("reuse_value_wrapper", ClickHouseDataConfig.DEFAULT_REUSE_VALUE_WRAPPER,
"Whether to reuse wrapper of value(e.g. ClickHouseValue or ClickHouseRecord) for memory efficiency."),
/**
* Server revision.
*/
SERVER_REVISION("server_revision", 54442, "Server revision."),
/**
* Server timezone.
*/
SERVER_TIME_ZONE("server_time_zone", "", "Server timezone."),
/**
* Server version.
*/
SERVER_VERSION("server_version", "", "Server version."),
/**
* Session id.
*/
SESSION_ID("session_id", "", "Session id"),
/**
* Whether to check if session id is validate.
*/
SESSION_CHECK("session_check", false, "Whether to check if existence of session id."),
/**
* Session timeout in seconds.
*/
SESSION_TIMEOUT("session_timeout", 0,
"Session timeout in seconds. 0 or negative number means same as server default."),
/**
* Socket timeout in milliseconds.
*/
SOCKET_TIMEOUT("socket_timeout", ClickHouseDataConfig.DEFAULT_TIMEOUT, "Socket timeout in milliseconds."),
/**
* Whether allows for the reuse of local addresses and ports. See
* {@link java.net.StandardSocketOptions#SO_REUSEADDR}.
*/
SOCKET_REUSEADDR("socket_reuseaddr", false,
"Whether allows for the reuse of local addresses and ports. "
+ "Only works for client using custom Socket(e.g. TCP client or HTTP provider with custom SocketFactory etc.)."),
/**
* Whether to enable keep-alive packets for a socket connection. See
* {@link java.net.StandardSocketOptions#SO_KEEPALIVE}.
*/
SOCKET_KEEPALIVE("socket_keepalive", false,
"Whether to enable keep-alive packets for a socket connection. Only works for client using custom Socket."),
/**
* Seconds to wait while data is being transmitted before closing the socket.
* Use negative number to disable the option. See
* {@link java.net.StandardSocketOptions#SO_LINGER}.
*/
SOCKET_LINGER("socket_linger", -1,
"Seconds to wait while data is being transmitted before closing the socket. Use negative number to disable the option. "
+ "Only works for client using custom Socket(e.g. TCP client or HTTP provider with custom SocketFactory etc.)."),
/**
* Type-of-service(TOS) or traffic class field in the IP header for a socket.
* See {@link java.net.StandardSocketOptions#IP_TOS}.
*/
SOCKET_IP_TOS("socket_ip_tos", 0,
"Socket IP_TOS option which indicates IP package priority. Only works for client using custom Socket."),
/**
* See {@link java.net.StandardSocketOptions#TCP_NODELAY}.
*/
SOCKET_TCP_NODELAY("socket_tcp_nodelay", false, ""),
/**
* Size of the socket receive buffer in bytes. See
* {@link java.net.StandardSocketOptions#SO_RCVBUF}.
*/
SOCKET_RCVBUF("socket_rcvbuf", 0,
"Size of the socket receive buffer in bytes. Only works for client using custom Socket."),
/**
* Size of the socket send buffer in bytes. See
* {@link java.net.StandardSocketOptions#SO_SNDBUF}.
*/
SOCKET_SNDBUF("socket_sndbuf", 0,
"Size of the socket send buffer in bytes. Only works for client using custom Socket."),
// TODO: new and extended socket options(e.g SO_REUSEPORT and TCP_QUICKACK etc.)
/**
* Whether to enable SSL for the connection.
*/
SSL("ssl", false, "Whether to enable SSL/TLS for the connection."),
/**
* SSL mode.
*/
SSL_MODE("sslmode", ClickHouseSslMode.STRICT, "verify or not certificate: none (don't verify), strict (verify)"),
/**
* SSL root certificiate.
*/
SSL_ROOT_CERTIFICATE("sslrootcert", "", "SSL/TLS root certificates."),
/**
* SSL certificiate.
*/
SSL_CERTIFICATE("sslcert", "", "SSL/TLS certificate."),
/**
* SSL key.
*/
SSL_KEY("sslkey", "", "RSA key in PKCS#8 format.", true),
/**
* Key Store type.
*/
KEY_STORE_TYPE("key_store_type", "", "Specifies the type or format of the keystore/truststore file used for SSL/TLS configuration, such as \"JKS\" (Java KeyStore) or \"PKCS12.\"", true),
/**
* Trust Store.
*/
TRUST_STORE("trust_store", "", "Path to the truststore file", true),
/**
* Trust Store password.
*/
KEY_STORE_PASSWORD("key_store_password", "", "Password needed to access the keystore file specified in the keystore config", true),
/**
* Transaction timeout in seconds.
*/
TRANSACTION_TIMEOUT("transaction_timeout", 0,
"Transaction timeout in seconds. 0 or negative number means same as session_timeout."),
/**
* Whether to convert unsigned types to the next widest type(e.g. use
* {@code short} for UInt8 instead of {@code byte}, and {@code UnsignedLong} for
* UInt64).
*/
WIDEN_UNSIGNED_TYPES("widen_unsigned_types", ClickHouseDataConfig.DEFAULT_WIDEN_UNSIGNED_TYPE,
"Whether to convert unsigned types to the next widest type(e.g. use short for UInt8 instead of byte, and UnsignedLong for UInt64)."),
/**
* Whether to support binary string. Enable this option to treat
* {@code FixedString} and {@code String} as byte array.
*/
USE_BINARY_STRING("use_binary_string", ClickHouseDataConfig.DEFAULT_USE_BINARY_STRING,
"Whether to support binary string. Enable this option to treat FixedString and String as byte array."),
/**
* Whether to use blocking queue for buffering.
*/
USE_BLOCKING_QUEUE("use_blocking_queue", ClickHouseDataConfig.DEFAULT_USE_BLOCKING_QUEUE,
"Whether to use blocking queue for buffering."),
/**
* Whether to use compilation(generated byte code) in object mapping and
* serialization.
*/
USE_COMPILATION("use_compilation", ClickHouseDataConfig.DEFAULT_USE_COMPILATION,
"Whether to use compilation(generated byte code) in object mapping and serialization."),
/**
* Whether Object[] should be used instead of primitive arrays.
*/
USE_OBJECTS_IN_ARRAYS("use_objects_in_arrays", ClickHouseDataConfig.DEFAULT_USE_OBJECT_IN_ARRAY,
"Whether Object[] should be used instead of primitive arrays."),
/**
* Type of proxy can be used to access ClickHouse server. To use an HTTP/SOCKS
* proxy, you must specify the {@link #PROXY_HOST} and {@link #PROXY_PORT}.
*/
PROXY_TYPE("proxy_type", ClickHouseProxyType.IGNORE,
"Type of proxy can be used to access ClickHouse server. To use an HTTP/SOCKS proxy, you must specify proxy_host and proxy_port."),
/**
* Set Clickhouse proxy hostname.
*/
PROXY_HOST("proxy_host", "", "Set ClickHouse server proxy hostname."),
/**
* Set ClickHouse proxy port.
*/
PROXY_PORT("proxy_port", -1, "Set ClickHouse server proxy hostname."),
/**
* Whether to use server time zone.
*/
USE_SERVER_TIME_ZONE("use_server_time_zone", true,
"Whether to use server time zone. On connection init select timezone() will be executed"),
/**
* Whether to use time zone from server for Date.
*/
USE_SERVER_TIME_ZONE_FOR_DATES("use_server_time_zone_for_dates", false,
"Whether to use timezone from server on Date parsing in getDate(). "
+ "If false, Date returned is a wrapper of a timestamp at start of the day in client timezone. "
+ "If true - at start of the day in server or use_time_zone timezone."),
/**
* Custom time zone. Only works when {@code use_server_time_zone} is set to
* false.
*/
USE_TIME_ZONE("use_time_zone", "", "Time zone of all DateTime* values. "
+ "Only used when use_server_time_zone is false. Empty value means client time zone."),
/**
* Query ID to be attached to an operation
*/
QUERY_ID("query_id", "", "Query id"),
/**
* Connection time to live in milliseconds. 0 or negative number means no limit.
* Can be used to override keep-alive time suggested by a server.
*/
CONNECTION_TTL("connection_ttl", 0L,
"Connection time to live in milliseconds. 0 or negative number means no limit."),
;
private final String key;
private final Serializable defaultValue;
private final Class<? extends Serializable> clazz;
private final String description;
private final boolean sensitive;
private static final Map<String, ClickHouseClientOption> options;
static final String UNKNOWN = "unknown";
public static final String LATEST_KNOWN_VERSION = "0.6.3";
/**
* Semantic version of the product.
*/
public static final String PRODUCT_VERSION;
/**
* Revision(shortened git commit hash) of the product.
*/
public static final String PRODUCT_REVISION;
/**
* Client O/S information in format of {@code <o/s name>/<o/s version>}.
*/
public static final String CLIENT_OS_INFO;
/**
* Client JVM information in format of {@code <jvm name>/<jvm version>}.
*/
public static final String CLIENT_JVM_INFO;
/**
* Client user name.
*/
public static final String CLIENT_USER;
/**
* Client host name.
*/
public static final String CLIENT_HOST;
static {
Map<String, ClickHouseClientOption> map = new HashMap<>();
for (ClickHouseClientOption o : values()) {
if (map.put(o.getKey(), o) != null) {
throw new IllegalStateException("Duplicated key found: " + o.getKey());
}
}
options = Collections.unmodifiableMap(map);
// <artifact-id> <version> (revision: <revision>)
String ver = ClickHouseClientOption.class.getPackage().getImplementationVersion();
String[] parts = ver == null || ver.isEmpty() ? null : ver.split("\\s");
if (parts != null && parts.length == 4 && parts[1].length() > 0 && parts[3].length() > 1
&& ver.charAt(ver.length() - 1) == ')') {
PRODUCT_VERSION = parts[1];
ver = parts[3];
PRODUCT_REVISION = ver.substring(0, ver.length() - 1);
} else { // perhaps try harder by checking version from pom.xml?
PRODUCT_VERSION = LATEST_KNOWN_VERSION;
PRODUCT_REVISION = UNKNOWN;
}
CLIENT_OS_INFO = new StringBuilder().append(getSystemConfig("os.name", "O/S")).append('/')
.append(getSystemConfig("os.version", UNKNOWN)).toString();
String javaVersion = System.getProperty("java.vendor.version");
if (javaVersion == null || javaVersion.isEmpty() || javaVersion.indexOf(' ') >= 0) {
javaVersion = getSystemConfig("java.vm.version", getSystemConfig("java.version", UNKNOWN));
}
CLIENT_JVM_INFO = new StringBuilder().append(getSystemConfig("java.vm.name", "Java")).append('/')
.append(javaVersion).toString();
CLIENT_USER = getSystemConfig("user.name", UNKNOWN);
try {
ver = InetAddress.getLocalHost().getHostName();
} catch (UnknownHostException e1) {
// ignore
}
CLIENT_HOST = ver == null || ver.isEmpty() ? UNKNOWN : ver;
}
/**
* Builds user-agent based on given product name. The user-agent will be
* something look like
* {@code <product name>/<product version> (<o/s name>/<o/s version>; <jvm name>/<jvm version>[; <additionalProperty>]; rv:<product revision>)}.
*
* @param productName product name, null or blank string is treated as
* {@code ClickHouse Java Client}
* @param additionalProperty additional property if any
* @return non-empty user-agent
*/
public static String buildUserAgent(String productName, String additionalProperty) {
productName = productName == null || productName.isEmpty() ? (String) PRODUCT_NAME.getEffectiveDefaultValue() : productName.trim();
StringBuilder builder = new StringBuilder(productName).append(PRODUCT_VERSION.isEmpty() ? "" : "/" + PRODUCT_VERSION);
if (!String.valueOf(PRODUCT_NAME.getDefaultValue()).equals(productName)) {//Append if someone changed the original value
builder.append(" ").append(PRODUCT_NAME.getDefaultValue()).append(LATEST_KNOWN_VERSION);
}
builder.append(" (").append(CLIENT_JVM_INFO);
if (additionalProperty != null && !additionalProperty.isEmpty()) {
builder.append("; ").append(additionalProperty.trim());
}
return builder.append(")").toString();
}
/**
* Gets system property and fall back to the given value as needed.
*
* @param propertyName non-null property name
* @param defaultValue default value, only useful if it's not null
* @return property value
*/
public static String getSystemConfig(String propertyName, String defaultValue) {
final String propertyValue = System.getProperty(propertyName);
if (defaultValue == null) {
return propertyValue;
}
return propertyValue == null || propertyValue.isEmpty() ? defaultValue : propertyValue;
}
/**
* Gets client option by key.
*
* @param key key of the option
* @return client option object, or null if not found
*/
public static ClickHouseClientOption fromKey(String key) {
return options.get(key);
}
/**
* Constructor of an option for client.
*
* @param <T> type of the value, usually either String or Number(e.g.
* int, long etc.)
* @param key non-null key, better use snake_case instead of camelCase
* for consistency
* @param defaultValue non-null default value
* @param description non-null description of this option
*/
<T extends Serializable> ClickHouseClientOption(String key, T defaultValue, String description) {
this(key, defaultValue, description, false);
}
/**
* Constructor of client option.
*
* @param <T> type of the value, usually either String or Number(e.g.
* int, long etc.)
* @param key non-null key, better use snake_case instead of camelCase
* for consistency
* @param defaultValue non-null default value
* @param description non-null description of this option
* @param sensitive whether the option is sensitive or not
*/
<T extends Serializable> ClickHouseClientOption(String key, T defaultValue, String description, boolean sensitive) {
this.key = ClickHouseChecker.nonNull(key, "key");
this.defaultValue = ClickHouseChecker.nonNull(defaultValue, "defaultValue");
this.clazz = defaultValue.getClass();
this.description = ClickHouseChecker.nonNull(description, "description");
this.sensitive = sensitive;
}
@Override
public Serializable getDefaultValue() {
return defaultValue;
}
@Override
public String getDescription() {
return description;
}
@Override
public String getKey() {
return key;
}
@Override
public Class<? extends Serializable> getValueType() {
return clazz;
}
@Override
public boolean isSensitive() {
return sensitive;
}
}