README.md

# RowBinary

Library for working with ClickHouse's [RowBinary](https://clickhouse.yandex/docs/en/interfaces/formats/#rowbinary "ClickHouse RowBinary Format") format. 

Currently, the library only supports encoding to *RowBinary* format. A decoder might be implemented later. 
This library is meant to be used for ingestion data into ClickHouse with Elixir efficiently.


## Installation

The package can be installed by adding `rowbinary` to your list of dependencies in `mix.exs`:

```elixir
def deps do
  [
    {:rowbinary, "~> 0.1.0"}
  ]
end
```

## Usage

`RowBinary.encode/2` can be used to encode Elixir data into ClickHouse RowBinary-encoded binaries. Additionally, a protocol spec `RowBinary.RowBinaryEncoding` is included to help with implementing encoders for structs or maps.

### Examples:
```elixir
    iex> RowBinary.encode(17, [:int8])
    <<17>>


    iex> RowBinary.encode("hello", [:enum8, %{"hello" => 0, "world" => 1}])
    <<0>>


    iex> RowBinary.encode(["foo", nil, "barbazbarbaz"], [:array, :nullable, :fixedstring, 8])
    <<3, 0, 102, 111, 111, 0, 0, 0, 0, 0, 1, 0, 98, 97, 114, 98, 97, 122, 98, 97>>


    iex> RowBinary.encode(1337, [:int8]) # 1137 is out of range for 8 bit integers
    ** (ArgumentError) value=1337 with wrong types=[:int8]
```
`RowBinary.encode/2` takes a value that should be encoded and a type definition. See `RowBinary.encode/2` for information about supported types.

## Limitations

  * **Decimal** and **AggregateFunction** types are not supported
  * Type definitions are not checked before encoding. Types like *Nullable(Array(Int8))* are not allowed in ClickHouse, but `RowBinary.encode/2` will generate a result for now. Keep that in mind.

## Testing

  * Not all unit test are done yet, but will be gradually updated.
  * You can run `mix generate_test_cases` to generate ExUnit test cases with data directly pulled from a local ClickHouse server.


## Benchmarks

```
Name                                  ips        average  deviation         median         99th %
float32                           13.44 M       74.38 ns ±31997.44%          46 ns          97 ns
float64                           13.42 M       74.54 ns ±31437.63%          39 ns         173 ns
int16                             12.83 M       77.92 ns ±34046.24%          42 ns          93 ns
uint16                            12.23 M       81.78 ns ±32837.36%          43 ns         102 ns
uint8                             11.68 M       85.63 ns ±31902.38%          47 ns         115 ns
int32                             11.47 M       87.18 ns ±30597.14%          47 ns         107 ns
int8                              11.40 M       87.73 ns ±31150.32%          48 ns         118 ns
uint32                            10.93 M       91.48 ns ±30263.29%          52 ns         110 ns
int64                              8.97 M      111.50 ns ±21277.66%          82 ns         159 ns
uint64                             8.09 M      123.63 ns ±25362.26%          83 ns         264 ns
fixedstring_medium                 7.99 M      125.18 ns ±29659.83%          61 ns         103 ns
fixedstring_short                  7.49 M      133.54 ns ±29224.88%          61 ns          96 ns
enum16                             7.06 M      141.70 ns ±12062.72%         107 ns         185 ns
enum8                              6.81 M      146.92 ns ±12132.97%         109 ns         241 ns
int16_nullable                     6.26 M      159.70 ns ±19120.97%         101 ns         237 ns
float32_nullable                   6.25 M      159.91 ns ±19210.34%         101 ns         232 ns
uint8_nullable                     6.14 M      162.81 ns ±19420.34%         100 ns         350 ns
uint16_nullable                    6.04 M      165.56 ns ±18865.28%         108 ns         234 ns
int32_nullable                     6.01 M      166.30 ns ±18483.14%         106 ns         349 ns
int8_nullable                      5.85 M      170.89 ns ±19343.78%         105 ns         413 ns
float64_nullable                   5.64 M      177.17 ns ±19409.67%          99 ns         226 ns
fixedstring_nullable_short         5.61 M      178.26 ns ±18491.88%         125 ns         246 ns
ipv4                               5.48 M      182.52 ns  ±9926.33%         145 ns         211 ns
uint32_nullable                    5.46 M      183.14 ns ±17913.89%         109 ns         445 ns
uint64_nullable                    5.12 M      195.19 ns ±12095.99%         145 ns         344 ns
enum8_nullable                     4.37 M      228.63 ns ±13658.96%         169 ns         314 ns
enum16_nullable                    4.31 M      232.22 ns ±13503.33%         173 ns         329 ns
int64_nullable                     4.28 M      233.47 ns ±15233.64%         151 ns         323 ns
ipv6                               4.11 M      243.57 ns  ±5280.01%         216 ns         348 ns
ipv4_nullable                      3.67 M      272.79 ns ±11722.87%         207 ns         414 ns
string_medium                      3.61 M      276.79 ns   ±214.24%         251 ns         542 ns
string_short                       3.23 M      309.88 ns  ±5660.74%         186 ns        1738 ns
date                               2.79 M      358.03 ns  ±7836.94%         288 ns         611 ns
ipv6_nullable                      2.78 M      360.14 ns  ±9366.41%         279 ns         646 ns
string_large                       2.64 M      378.87 ns    ±53.17%         303 ns         615 ns
fixedstring_nullable_medium        2.59 M      385.93 ns ±11247.24%         199 ns         469 ns
date_nullable                      2.21 M      452.19 ns  ±8436.48%         350 ns         705 ns
string_nullable_short              2.19 M      456.62 ns  ±8237.23%         242 ns         774 ns
fixedstring_nullable_large         2.02 M      494.99 ns  ±6464.26%         247 ns        1475 ns
fixedstring_large                  1.96 M      509.81 ns  ±6193.13%         248 ns        1659 ns
datetime                           1.48 M      674.67 ns  ±4135.51%         585 ns        1000 ns
datetime_nullable                  1.33 M      752.78 ns  ±3806.41%         656 ns        1118 ns
string_nullable_medium             1.26 M      795.26 ns  ±4828.47%         384 ns        1191 ns
string_nullable_large              0.88 M     1136.22 ns  ±2881.13%         644 ns        1392 ns
array_short                        0.75 M     1331.87 ns  ±2054.50%        1044 ns        2544 ns
uuid_hex                           0.26 M     3827.59 ns   ±504.17%        3411 ns        6774 ns
uuid_hex_nullable                  0.26 M     3904.76 ns   ±537.69%        3472 ns        6772 ns
uuid_default                       0.25 M     3979.64 ns   ±359.59%        3551 ns        9099 ns
uuid_default_nullable              0.24 M     4089.80 ns   ±378.71%        3629 ns     9390.95 ns
array_long                        0.112 M     8946.26 ns   ±158.33%        8180 ns       18199 ns
array_large                      0.0121 M    82707.29 ns    ±29.05%       83042 ns    97103.83 ns
```