Java client library to communicate with a DB server through its protocols. The current implementation only supports the HTTP interface.
The library provides its own API to send requests to a server. The library also provides tools to work with different binary data formats (RowBinary* & Native*).
Authentication by an access token requires setting access token by calling Authentication by a SSL Client Certificate require setting username, enabling SSL Authentication, setting a client certificate and a client key by calling
will result in the following Application can set own http header ⚠️ When options are set via When options are set via ParametersParametersParametersParametersParametersParametersParametersParametersV2 Insert TSV formatted data.
Setup
- Maven Central (project web page): https://mvnrepository.com/artifact/com.clickhouse/client-v2
- Nightly builds (repository link): https://central.sonatype.com/repository/maven-snapshots/
- Old Nightly builds artifactory (repository link): https://s01.oss.sonatype.org/content/repositories/snapshots/
- Maven
- Gradle (Kotlin)
- Gradle
Initialization
The Client object is initialized bycom.clickhouse.client.api.Client.Builder#build(). Each client has its own context and no objects are shared between them.
The Builder has configuration methods for convenient setup.Example:showLineNumbers
Client is AutoCloseable and should be closed when not needed anymore.Authentication
Authentication is configured per client at the initialization phase. There are three authentication methods supported: by password, by access token, by SSL Client Certificate.Authentication by a password requires setting user name password by callingsetUsername(String) and setPassword(String):showLineNumbers
setAccessToken(String):showLineNumbers
setUsername(String), useSSLAuthentication(boolean), setClientCertificate(String) and setClientKey(String) accordingly:showLineNumbers
SSL Authentication may be hard to troubleshoot on production because many errors from SSL libraries provide not enough information. For example, if client certificate and key don’t match then server will terminate connection immediately (in case of HTTP it will be connection initiation stage where no HTTP requests are send so no response is sent).Please use tools like openssl to verify certificates and keys:
- check key integrity:
openssl rsa -in [key-file.key] -check -noout - check client certificate has matching CN for a user:
- get CN from an user certificate -
openssl x509 -noout -subject -in [user.cert] - verify same value is set in database
select name, auth_type, auth_params from system.users where auth_type = 'ssl_certificate'(query will outputauth_paramswith something like{"common_names":["some_user"]})
- get CN from an user certificate -
Configuration
All settings are defined by instance methods (a.k.a configuration methods) that make the scope and context of each value clear. Major configuration parameters are defined in one scope (client or operation) and don’t override each other.Configuration is defined during client creation. Seecom.clickhouse.client.api.Client.Builder.Client Configuration
- Connection & Endpoints
- Authentication
- Timeouts & Retry
- Socket Options
- Compression
- SSL/Security
- Proxy
- HTTP & Headers
- Server Settings
- Timezone
- Advanced
Client Identification
There are two fields in a query log that identify application originated a request:client_name and http_user_agent. Native TCP protocol uses
client_name to identify application. HTTP protocol uses http_user_agent to identify application. Client builder has method setClientName correct values
for both protocols.
The field http_user_agent is set according to User-Agent header common format: application-name[/version] [(operating-system; architecture; ...)].
This set of values is repeated for each layer: application, client library, http client library. What is set by setClientName method comes first in the list.For example:showLineNumbers
http_user_agent value:User-Agent to identify itself. But part clickhouse-java-v2/0.9.6-SNAPSHOT will be appended to the end of the header.Operation Identification
Query log has another two fieldsquery_id and log_comment that can be used to identify an operation and add additional information to the query log.query_id is a unique identifier of an operation. It can be set by application by calling setQueryId method of the QuerySettings class.showLineNumbers
log_comment is a comment that can be added to the query log. It can be set by application by calling logComment method of the QuerySettings class.showLineNumbers
Server Settings
Server side settings can be set on the client level once while creation (seeserverSetting method of the Builder) and on operation level (see serverSetting for operation settings class).showLineNumbers
setOption method (either the Client.Builder or operation settings class) then server settings name should be prefixed with clickhouse_setting_. The com.clickhouse.client.api.ClientConfigProperties#serverSetting() may be handy in this case.Custom HTTP Header
Custom HTTP headers can be set for all operations (client level) or a single one (operation level).showLineNumbers
setOption method (either the Client.Builder or operation settings class) then custom header name should be prefixed with http_header_. Method com.clickhouse.client.api.ClientConfigProperties#httpHeader() may be handy in this case.Common Definitions
ClickHouseFormat
Enum of supported formats. It includes all formats that ClickHouse supports.raw- user should transcode raw datafull- the client can transcode data by itself and accepts a raw data stream-- operation not supported by ClickHouse for this format
Insert API
insert(String tableName, InputStream data, ClickHouseFormat format)
Accepts data as anInputStream of bytes in the specified format. It is expected that data is encoded in the format.SignaturestableName - a target table name.data - an input stream of an encoded data.format - a format in which the data is encoded.settings - request settings.Return valueFuture of InsertResponse type - result of the operation and additional information like server side metrics.ExamplesshowLineNumbers
insert(String tableName, List<?> data, InsertSettings settings)
Sends a write request to database. The list of objects is converted into an efficient format and then is sent to a server. The class of the list items should be registered up-front usingregister(Class, TableSchema) method.SignaturestableName - name of the target table.data - collection DTO (Data Transfer Object) objects.settings - request settings.Return valueFuture of InsertResponse type - the result of the operation and additional information like server side metrics.ExamplesshowLineNumbers
InsertSettings
Configuration options for insert operations.Configuration methodsInsertResponse
Response object that holds result of insert operation. It is only available if the client got response from a server.This object should be closed as soon as possible to release a connection because the connection can’t be re-used until all data of previous response is fully read.
Query API
query(String sqlQuery)
SendssqlQuery as is. Response format is set by query settings. QueryResponse will hold a reference to the response stream that should be consumed by a reader for the supportig format.SignaturessqlQuery - a single SQL statement. The Query is sent as is to a server.settings - request settings.Return valueFuture of QueryResponse type - a result dataset and additional information like server side metrics. The Response object should be closed after consuming the dataset.Examplesquery(String sqlQuery, Map<String, Object> queryParams, QuerySettings settings)
SendssqlQuery as is. Additionally will send query parameters so the server can compile the SQL expression.SignaturessqlQuery - sql expression with placeholders {}.queryParams - map of variables to complete the sql expression on server.settings - request settings.Return valueFuture of QueryResponse type - a result dataset and additional information like server side metrics. The Response object should be closed after consuming the dataset.ExamplesshowLineNumbers
queryAll(String sqlQuery)
Queries a data inRowBinaryWithNamesAndTypes format. Returns the result as a collection. Read performance is the same as with the reader but more memory is required to hold the whole dataset.SignaturessqlQuery - sql expression to query data from a server.Return valueComplete dataset represented by a list of GenericRecord objects that provide access in row style for the result data.ExamplesshowLineNumbers
QuerySettings
Configuration options for query operations.Configuration methodsQueryResponse
Response object that holds result of query execution. It is only available if the client got a response from a server.This object should be closed as soon as possible to release a connection because the connection can’t be re-used until all data of previous response is fully read.
Examples
- Example code is available in repo
- Reference Spring Service implementation
Common API
getTableSchema(String table)
Fetches table schema for thetable.Signaturestable - table name for which schema data should be fetched.database - database where the target table is defined.Return valueReturns a TableSchema object with list of table columns.getTableSchemaFromQuery(String sql)
Fetches schema from a SQL statement.Signaturessql - “SELECT” SQL statement which schema should be returned.Return valueReturns a TableSchema object with columns matching the sql expression.TableSchema
register(Class<?> clazz, TableSchema schema)
Compiles serialization and deserialization layer for the Java Class to use for writing/reading data withschema. The method will create a serializer and deserializer for the pair getter/setter and corresponding column.
Column match is found by extracting its name from a method name. For example, getFirstName will be for the column first_name or firstname.Signaturesclazz - Class representing the POJO used to read/write data.schema - Data schema to use for matching with POJO properties.ExamplesshowLineNumbers
Usage Examples
Complete examples code is stored in the repo in a ‘example` folder:- client-v2 - main set of examples.
- demo-service - example of how to use the client in a Spring Boot application.
- demo-kotlin-service - example of how to use the client in Ktor (Kotlin) application.
Reading Data
There are two common ways to read data:query()method that returns low-levelQueryResponseobject that containsInputStreamwith data. Usually combined withClickHouseBinaryFormatReaderfor streaming reads but can be used with any other custom reader implementation.QueryResponsealso provides access to the result set metadata and metrics.queryAll()method and usingGenericRecordfor convenient row access. In this case the whole result set is loaded into memory.queryRecords()method that returnscom.clickhouse.client.api.query.Records- an iterator forGenericRecordobjects. This method uses streaming approach (no data is loaded into memory) and utilisesGenericRecordto access data.
Reading Arrays
ClickHouseBinaryFormatReader MethodsgetList(...)- reads anyArray(...)asList<T>. Good default for flexible typed reads. Supports nested arrays.getByteArray(...),getShortArray(...),getIntArray(...),getLongArray(...),getFloatArray(...),getDoubleArray(...),getBooleanArray(...)- best for 1D arrays of primitive-compatible values.getStringArray(...)- forArray(String)(and enum values represented as names).getObjectArray(...)- generic option for anyArray(...)element type, including nested arrays. Use to read arrays with nullable values and nested arrays.
GenericRecord MethodsgetList(...)- reads anyArray(...)asList<T>. Good default for flexible typed reads. Supports nested arrays.getByteArray(...),getShortArray(...),getIntArray(...),getLongArray(...),getFloatArray(...),getDoubleArray(...),getBooleanArray(...)- best for 1D arrays of primitive-compatible values.getStringArray(...)- forArray(String)(and enum values represented as names).getObjectArray(...)- generic option for anyArray(...)element type, including nested arrays. Use to read arrays with nullable values and nested arrays.
Migration Guide
Old client (V1) was usingcom.clickhouse.client.ClickHouseClient#builder as start point. The new client (V2) uses similar pattern with com.clickhouse.client.api.Client.Builder. Main
differences are:- no service loader is used to grab implementation. The
com.clickhouse.client.api.Clientis facade class for all kinds of implementation in the future. - a fewer sources of configuration: one is provided to the builder and one is with operation settings (
QuerySettings,InsertSettings). Previous version had configuration per node and was loading env. variables in some cases.
Configuration Parameters Match
There are 3 enum classes related to configuration in V1:com.clickhouse.client.config.ClickHouseDefaults- configuration parameters that supposed to be set in most use cases. LikeUSERandPASSWORD.com.clickhouse.client.config.ClickHouseClientOption- configuration parameters specific for the client. LikeHEALTH_CHECK_INTERVAL.com.clickhouse.client.http.config.ClickHouseHttpOption- configuration parameters specific for HTTP interface. LikeRECEIVE_QUERY_PROGRESS.
com.clickhouse.client.config.ClickHouseDefaults#ASYNC and
com.clickhouse.client.config.ClickHouseClientOption#ASYNC). The new V2 client uses com.clickhouse.client.api.Client.Builder as single dictionary of all possible client configuration options.There is
com.clickhouse.client.api.ClientConfigProperties where all configuration parameter names are listed.Table below shows what old options are supported in the new client and their new meaning.Legend: ✔ = supported, ✗ = dropped- Connection & Auth
- SSL & Security
- Socket Options
- Compression
- Proxy
- Timeouts & Retry
- Timezone
- Buffers & Performance
- Threading & Async
- HTTP & Headers
- Format & Query
- Node Discovery & Load Balancing
- Miscellaneous
General Differences
- Client V2 uses less proprietary classes to increase portability. For example, V2 works with any implementation of
java.io.InputStreamfor writing data to a server. - Client V2
asyncsettings isoffby default. It means no extra threads and more application control over client. This setting should beofffor majority of use cases. Enablingasyncwill create a separate thread for a request. It only make sense when using application controlled executor (seecom.clickhouse.client.api.Client.Builder#setSharedOperationExecutor)
Writing Data
- use any implementation of
java.io.InputStream. V1com.clickhouse.data.ClickHouseInputStreamis supported but NOT recommended. - once end of input stream is detected it handled accordingly. Previously output stream of a request should be closed.
- there is a single method to call. No need to create an additional request object.
- request body stream is closed automatically when all data is copied.
- new low-level API is available
com.clickhouse.client.api.Client#insert(java.lang.String, java.util.List<java.lang.String>, com.clickhouse.client.api.DataStreamWriter, com.clickhouse.data.ClickHouseFormat, com.clickhouse.client.api.insert.InsertSettings).com.clickhouse.client.api.DataStreamWriteris designed to implement custom data writing logic. For instance, reading data from a queue.
Reading Data
- Data is read in
RowBinaryWithNamesAndTypesformat by default. Currently only this format is supported when data binding is required. - Data can be read as a collection of records using
List<GenericRecord> com.clickhouse.client.api.Client#queryAll(java.lang.String)method. It will read data to a memory and release connection. No need for extra handling.GenericRecordgives access to data, implements some conversions.