Please check the build logs for more information.
See Builds for ideas on how to fix a failed build, or Metadata for how to configure docs.rs builds.
If you believe this is docs.rs' fault, open an issue.
clickhouse.rs
A typed client for ClickHouse.
Note: This is a fork of bk-rs/clickhouse-rs
- Uses
serdefor encoding/decoding rows. - Supports
serdeattributes:skip_serializing,skip_deserializing,rename. - Uses
RowBinaryencoding over HTTP transport.- There are plans to switch to
Nativeover TCP.
- There are plans to switch to
- Supports TLS.
- Supports compression and decompression (LZ4 and LZ4HC).
- Provides API for selecting.
- Provides API for inserting.
- Provides API for infinite transactional (see below) inserting.
- Provides API for watching live views.
- Provides mocks for unit testing.
Note: ch2rs is useful to generate a row type from ClickHouse.
Usage
To use the crate, add this to your Cargo.toml:
[]
= "0.11.6"
[]
= { = "0.11.6", = ["test-util"] }
Note about ClickHouse prior to v22.6
CH server older than v22.6 (2022-06-16) handles RowBinary incorrectly in some rare cases. Use 0.11 and enable wa-37420 feature to solve this problem. Don't use it for newer versions.
Create a client
use Client;
let client = default
.with_url
.with_user
.with_password
.with_database;
- Reuse created clients or clone them in order to reuse a connection pool.
Select rows
use Deserialize;
use Row;
let mut cursor = client
.query
.bind
.bind
.?;
while let Some = cursor.next.await?
- Placeholder
?fieldsis replaced withno, name(fields ofRow). - Placeholder
?is replaced with values in followingbind()calls. - Convenient
fetch_one::<Row>()andfetch_all::<Row>()can be used to get a first row or all rows correspondingly. sql::Identifiercan be used to bind table names.
Note that cursors can return an error even after producing some rows. To avoid this, use client.with_option("wait_end_of_query", "1") in order to enable buffering on the server-side. More details. The buffer_size option can be useful too.
Insert a batch
use Serialize;
use Row;
let mut insert = client.insert?;
insert.write.await?;
insert.write.await?;
insert.end.await?;
- If
end()isn't called, theINSERTis aborted. - Rows are being sent progressively to spread network load.
- ClickHouse inserts batches atomically only if all rows fit in the same partition and their number is less
max_insert_block_size.
Infinite inserting
Requires the inserter feature.
let mut inserter = client.inserter?
.with_timeouts
.with_max_bytes
.with_max_rows
.with_period;
inserter.write?;
inserter.write?;
let stats = inserter.commit.await?;
if stats.rows > 0
Inserterends an active insert incommit()if thresholds (max_bytes,max_rows,period) are reached.- The interval between ending active
INSERTs can be biased by usingwith_period_biasto avoid load spikes by parallel inserters. Inserter::time_left()can be used to detect when the current period ends. CallInserter::commit()again to check limits if your stream emits items rarely.- Time thresholds implemented by using quanta crate to speed the inserter up. Not used if
test-utilis enabled (thus, time can be managed bytokio::time::advance()in custom tests). - All rows between
commit()calls are inserted in the sameINSERTstatement. - Do not forget to flush if you want to terminate inserting:
inserter.end.await?;
Perform DDL
client.query.execute.await?;
Live views
Requires the watch feature.
let mut cursor = client
.watch
.?;
let = cursor.next.await?.unwrap;
println!;
// Use `only_events()` to iterate over versions only.
let mut cursor = client.watch.limit.only_events.fetch?;
println!;
- Use carefully.
- This code uses or creates if not exists a temporary live view named
lv_{sha1(query)}to reuse the same live view by parallel watchers. - You can specify a name instead of a query.
- This API uses
JSONEachRowWithProgressunder the hood because of the issue. - Only struct rows can be used. Avoid
fetch::<u64>()and other without specified names.
See examples.
Feature Flags
lz4(enabled by default) — enablesCompression::Lz4andCompression::Lz4Hc(_)variants. If enabled,Compression::Lz4is used by default for all queries except forWATCH.tls(enabled by default) — supports urls with theHTTPSschema.inserter— enablesclient.inserter().test-util— adds mocks. See the example. Use it only indev-dependencies.watch— enablesclient.watchfunctionality. See the corresponding section for details.uuid— addsserde::uuidto work with uuid crate.time— addsserde::timeto work with time crate.
Data Types
-
(U)Int(8|16|32|64|128)maps to/from corresponding(u|i)(8|16|32|64|128)types or newtypes around them. -
(U)Int256aren't supported directly, but there is a workaround for it. -
Float(32|64)maps to/from correspondingf(32|64)or newtypes around them. -
Decimal(32|64|128)maps to/from correspondingi(32|64|128)or newtypes around them. It's more convenient to use fixnum or another implementation of signed fixed-point numbers. -
Booleanmaps to/fromboolor newtypes around it. -
Stringmaps to/from any string or bytes types, e.g.&str,&[u8],String,Vec<u8>orSmartString. Newtypes are also supported. To store bytes, consider using serde_bytes, because it's more efficient. -
FixedString(_)isn't supported yet. -
Enum(8|16)are supported using serde_repr.use ; -
UUIDmaps to/fromuuid::Uuidby usingserde::uuid. Requires theuuidfeature. -
IPv6maps to/fromstd::net::Ipv6Addr. -
IPv4maps to/fromstd::net::Ipv4Addrby usingserde::ipv4. -
Datemaps to/fromu16or a newtype around it and represents a number of days elapsed since1970-01-01. Also,time::Dateis supported by usingserde::time::date, that requires thetimefeature. -
Date32maps to/fromi32or a newtype around it and represents a number of days elapsed since1970-01-01. Also,time::Dateis supported by usingserde::time::date32, that requires thetimefeature. -
DateTimemaps to/fromu32or a newtype around it and represents a number of seconds elapsed since UNIX epoch. Also,time::OffsetDateTimeis supported by usingserde::time::datetime, that requires thetimefeature. -
DateTime64(_)maps to/fromi32or a newtype around it and represents a time elapsed since UNIX epoch. Also,time::OffsetDateTimeis supported by usingserde::time::datetime64::*, that requires thetimefeature. -
Typle(A, B, ...)maps to/from(A, B, ...)or a newtype around it. -
Array(_)maps to/from any slice, e.g.Vec<_>,&[_]. Newtypes are also supported. -
Map(K, V)behaves likeArray((K, V)). -
LowCardinality(_)is supported seamlessly. -
Nullable(_)maps to/fromOption<_>. Forclickhouse::serde::*helpers add::option. -
Nestedis supported by providing multiple arrays with renaming.// CREATE TABLE test(items Nested(name String, count UInt32)) -
JSONandGeoaren't supported for now.
Mocking
The crate provides utils for mocking CH server and testing DDL, SELECT, INSERT and WATCH queries.
The functionality can be enabled with the test-util feature. Use it only in dev-dependencies.
See the example.