Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/linux.yml
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ jobs:
-D CMAKE_C_COMPILER=${{matrix.C_COMPILER}} \
-D CMAKE_CXX_COMPILER=${{matrix.CXX_COMPILER}} \
-D CMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} \
-D CH_MAP_BOOL_TO_UINT8=OFF \
-D BUILD_TESTS=ON \
${{matrix.SSL_CMAKE_OPTION}} \
${{matrix.DEPENDENCIES_CMAKE_OPTIONS}} \
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/macos.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ jobs:
run: |
cmake \
-D CMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} \
-D CH_MAP_BOOL_TO_UINT8=OFF \
-D BUILD_TESTS=ON \
${{matrix.SSL_CMAKE_OPTION}} \
-S ${{github.workspace}} \
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/windows_mingw.yml
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ jobs:
tar
- name: Configure CMake
run: cmake -B build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DBUILD_TESTS=ON -DCHECK_VERSION=OFF
run: cmake -B build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCH_MAP_BOOL_TO_UINT8=OFF -DBUILD_TESTS=ON -DCHECK_VERSION=OFF
# -DWITH_OPENSSL=ON was not able to make it work (some strange issues with CA paths, need debug)
# -DCHECK_VERSION=OFF since it requires git, which can't be found from within cmake for some reason.

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/windows_msvc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ jobs:
- uses: ilammy/msvc-dev-cmd@v1

- name: Configure CMake
run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DBUILD_TESTS=ON
run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCH_MAP_BOOL_TO_UINT8=OFF -DBUILD_TESTS=ON

- name: Build
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}
Expand Down
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ OPTION (WITH_SYSTEM_ZSTD "Use system ZSTD" OFF)
OPTION (DEBUG_DEPENDENCIES "Print debug info about dependencies duting build" ON)
OPTION (CHECK_VERSION "Check that version number corresponds to git tag, usefull in CI/CD to validate that new version published on GitHub has same version in sources" OFF)
OPTION (DISABLE_CLANG_LIBC_WORKAROUND "Disable linking compiler-rt & gcc_s if using clang & libstdc++" OFF)
OPTION (CH_MAP_BOOL_TO_UINT8 "Map ClickHouse Bool type to UInt8 instead of exposing a distinct Bool API." ON)

PROJECT (CLICKHOUSE-CLIENT
VERSION "${CLICKHOUSE_CPP_VERSION}"
Expand Down
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ C++ client for [ClickHouse](https://clickhouse.com/).
## Supported data types

* Array(T)
* Bool (mapped to UInt8 by default; use `-DCH_MAP_BOOL_TO_UINT8=OFF` for a distinct `clickhouse::Bool`/`ColumnBool` API)
* Date
* DateTime, DateTime64
* DateTime([timezone]), DateTime64(N, [timezone])
Expand All @@ -26,6 +27,10 @@ C++ client for [ClickHouse](https://clickhouse.com/).
* JSON - experimental support; requires output_format_native_write_json_as_string=1; data is passed as strings


The distinct `Bool` type will become the default in some future version. The
current mapping to `UInt8` is provided only for compatibility and controlled via
`DCH_MAP_BOOL_TO_UINT8`.

## Dependencies
In the most basic case one needs only:
- a C++-17-complaint compiler,
Expand Down Expand Up @@ -258,5 +263,3 @@ client.Insert("default.test", block);
```sql
ALTER USER insert_account SETTINGS async_insert=1,wait_for_async_insert=1,async_insert_use_adaptive_busy_timeout=0,async_insert_busy_timeout_ms=5000,async_insert_max_data_size=104857600
```


7 changes: 7 additions & 0 deletions clickhouse/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ SET ( clickhouse-cpp-lib-src
base/endpoints_iterator.cpp

columns/array.cpp
columns/bool.cpp
columns/column.cpp
columns/date.cpp
columns/decimal.cpp
Expand Down Expand Up @@ -53,6 +54,7 @@ SET ( clickhouse-cpp-lib-src
base/wire_format.h

columns/array.h
columns/bool.h
columns/column.h
columns/date.h
columns/decimal.h
Expand Down Expand Up @@ -122,6 +124,11 @@ TARGET_LINK_LIBRARIES (clickhouse-cpp-lib
TARGET_INCLUDE_DIRECTORIES (clickhouse-cpp-lib
PUBLIC ${PROJECT_SOURCE_DIR}
)
IF (CH_MAP_BOOL_TO_UINT8)
TARGET_COMPILE_DEFINITIONS (clickhouse-cpp-lib PUBLIC CH_MAP_BOOL_TO_UINT8=1)
ELSE ()
TARGET_COMPILE_DEFINITIONS (clickhouse-cpp-lib PUBLIC CH_MAP_BOOL_TO_UINT8=0)
ENDIF ()

IF (NOT BUILD_SHARED_LIBS)
ADD_LIBRARY (clickhouse-cpp-lib-static ALIAS clickhouse-cpp-lib)
Expand Down
79 changes: 79 additions & 0 deletions clickhouse/columns/bool.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
#include "bool.h"

#include "../types/types.h"

#if !CH_MAP_BOOL_TO_UINT8

namespace clickhouse {

ColumnBool::ColumnBool()
: Column(Type::CreateSimple<bool>())
, data_()
{
}

ColumnBool::ColumnBool(std::vector<uint8_t> data)
: Column(Type::CreateSimple<bool>())
, data_(std::move(data))
{
}

void ColumnBool::Reserve(size_t new_cap) {
data_.Reserve(new_cap);
}

void ColumnBool::Append(bool value) {
data_.Append(static_cast<uint8_t>(value));
}

bool ColumnBool::At(size_t n) const {
return static_cast<bool>(data_.At(n));
}

void ColumnBool::Append(ColumnRef column) {
if (auto col = column->As<ColumnBool>()) {
auto& src = col->data_.GetWritableData();
data_.GetWritableData().insert(data_.GetWritableData().end(), src.begin(), src.end());
} else if (auto col = column->As<ColumnUInt8>()) {
auto& src = col->GetWritableData();
data_.GetWritableData().insert(data_.GetWritableData().end(), src.begin(), src.end());
}
}

bool ColumnBool::LoadBody(InputStream* input, size_t rows) {
return data_.LoadBody(input, rows);
}

void ColumnBool::SaveBody(OutputStream* output) {
data_.SaveBody(output);
}

void ColumnBool::Clear() {
data_.Clear();
}

size_t ColumnBool::Size() const {
return data_.Size();
}

ColumnRef ColumnBool::Slice(size_t begin, size_t len) const {
auto sliced = std::static_pointer_cast<ColumnUInt8>(data_.Slice(begin, len));
return std::make_shared<ColumnBool>(std::move(sliced->GetWritableData()));
}

ColumnRef ColumnBool::CloneEmpty() const {
return std::make_shared<ColumnBool>();
}

void ColumnBool::Swap(Column& other) {
auto& col = dynamic_cast<ColumnBool&>(other);
data_.Swap(col.data_);
}

ItemView ColumnBool::GetItem(size_t index) const {
return ItemView{Type::Bool, data_.At(index)};
}

} // namespace clickhouse

#endif // !CH_MAP_BOOL_TO_UINT8
63 changes: 63 additions & 0 deletions clickhouse/columns/bool.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#pragma once

#include "column.h"
#include "numeric.h"

#include "../types/types.h"

#if !CH_MAP_BOOL_TO_UINT8

#include <vector>

namespace clickhouse {

class ColumnBool : public Column {
public:
using ValueType = bool;

ColumnBool();
explicit ColumnBool(std::vector<uint8_t> data);

/// Increase the capacity of the column for large block insertion.
void Reserve(size_t new_cap) override;

/// Appends one element to the end of column.
void Append(bool value);

/// Returns element at given row number.
bool At(size_t n) const;

/// Returns element at given row number.
bool operator[](size_t n) const { return At(n); }

public:
/// Appends content of given column to the end of current one.
/// Accepts ColumnBool or ColumnUInt8.
void Append(ColumnRef column) override;

/// Loads column data from input stream.
bool LoadBody(InputStream* input, size_t rows) override;

/// Saves column data to output stream.
void SaveBody(OutputStream* output) override;

/// Clear column data.
void Clear() override;

/// Returns count of rows in the column.
size_t Size() const override;

/// Makes slice of the current column.
ColumnRef Slice(size_t begin, size_t len) const override;
ColumnRef CloneEmpty() const override;
void Swap(Column& other) override;

ItemView GetItem(size_t index) const override;

private:
ColumnUInt8 data_;
};

} // namespace clickhouse

#endif // !CH_MAP_BOOL_TO_UINT8
5 changes: 5 additions & 0 deletions clickhouse/columns/factory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "map.h"
#include "nothing.h"
#include "nullable.h"
#include "bool.h"
#include "numeric.h"
#include "string.h"
#include "./time.h" // `./` avoids possible conflicts with standard C time.h
Expand Down Expand Up @@ -50,6 +51,10 @@ static ColumnRef CreateTerminalColumn(const TypeAst& ast) {
case Type::Void:
return std::make_shared<ColumnNothing>();

#if !CH_MAP_BOOL_TO_UINT8
case Type::Bool:
return std::make_shared<ColumnBool>();
#endif
case Type::UInt8:
return std::make_shared<ColumnUInt8>();
case Type::UInt16:
Expand Down
3 changes: 3 additions & 0 deletions clickhouse/columns/itemview.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ void ItemView::ValidateData(Type::Code type, DataType data) {
case Type::Code::Int8:
case Type::Code::UInt8:
case Type::Code::Enum8:
#if !CH_MAP_BOOL_TO_UINT8
case Type::Code::Bool:
#endif
return AssertSize({1});

case Type::Code::Int16:
Expand Down
8 changes: 6 additions & 2 deletions clickhouse/columns/itemview.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@ struct ItemView {
inline auto ConvertToStorageValue(const T& t) {
if constexpr (std::is_same_v<std::string_view, T> || std::is_same_v<std::string, T>) {
return std::string_view{t};
} else if constexpr (std::is_fundamental_v<T> || std::is_same_v<Int128, std::decay_t<T>> || std::is_same_v<UInt128, std::decay_t<T>>) {
} else if constexpr (std::is_fundamental_v<T>
|| std::is_same_v<Int128, std::decay_t<T>>
|| std::is_same_v<UInt128, std::decay_t<T>>) {
return std::string_view{reinterpret_cast<const char*>(&t), sizeof(T)};
} else {
static_assert(!std::is_same_v<T, T>, "Unknown type, which can't be stored in ItemView");
Expand Down Expand Up @@ -65,7 +67,9 @@ struct ItemView {
using ValueType = std::remove_cv_t<std::decay_t<T>>;
if constexpr (std::is_same_v<std::string_view, ValueType> || std::is_same_v<std::string, ValueType>) {
return data;
} else if constexpr (std::is_fundamental_v<ValueType> || std::is_same_v<Int128, ValueType> || std::is_same_v<UInt128, ValueType>) {
} else if constexpr (std::is_fundamental_v<ValueType>
|| std::is_same_v<Int128, ValueType>
|| std::is_same_v<UInt128, ValueType>) {
if (sizeof(ValueType) == data.size()) {
return *reinterpret_cast<const T*>(data.data());
} else {
Expand Down
4 changes: 4 additions & 0 deletions clickhouse/types/type_parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,11 @@ static const std::unordered_map<std::string, Type::Code> kTypeCode = {
{ "Int16", Type::Int16 },
{ "Int32", Type::Int32 },
{ "Int64", Type::Int64 },
#if CH_MAP_BOOL_TO_UINT8
{ "Bool", Type::UInt8 },
#else
{ "Bool", Type::Bool },
#endif
{ "UInt8", Type::UInt8 },
{ "UInt16", Type::UInt16 },
{ "UInt32", Type::UInt32 },
Expand Down
9 changes: 9 additions & 0 deletions clickhouse/types/types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ const char* Type::TypeName(Type::Code code) {
case Type::Code::Time: return "Time";
case Type::Code::Time64: return "Time64";
case Type::Code::JSON: return "JSON";
#if !CH_MAP_BOOL_TO_UINT8
case Type::Code::Bool: return "Bool";
#endif
}

return "Unknown type";
Expand Down Expand Up @@ -87,6 +90,9 @@ std::string Type::GetName() const {
case Polygon:
case MultiPolygon:
case JSON:
#if !CH_MAP_BOOL_TO_UINT8
case Bool:
#endif
return TypeName(code_);
case Time64:
return As<Time64Type>()->GetName();
Expand Down Expand Up @@ -149,6 +155,9 @@ uint64_t Type::GetTypeUniqueId() const {
case Ring:
case Polygon:
case MultiPolygon:
#if !CH_MAP_BOOL_TO_UINT8
case Bool:
#endif
// For simple types, unique ID is the same as Type::Code
return code_;

Expand Down
15 changes: 15 additions & 0 deletions clickhouse/types/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,17 @@
#include <vector>
#include <stdexcept>

#ifndef CH_MAP_BOOL_TO_UINT8
#define CH_MAP_BOOL_TO_UINT8 1
#endif

namespace clickhouse {

using Int128 = absl::int128;
using UInt128 = absl::uint128;
using Int64 = int64_t;


using TypeRef = std::shared_ptr<class Type>;

class Type {
Expand Down Expand Up @@ -60,6 +65,9 @@ class Type {
Time,
Time64,
JSON,
#if !CH_MAP_BOOL_TO_UINT8
Bool,
#endif
};

using EnumItem = std::pair<std::string /* name */, int16_t /* value */>;
Expand Down Expand Up @@ -394,6 +402,13 @@ inline TypeRef Type::CreateSimple<uint64_t>() {
return TypeRef(new Type(UInt64));
}

#if !CH_MAP_BOOL_TO_UINT8
template <>
inline TypeRef Type::CreateSimple<bool>() {
return TypeRef(new Type(Bool));
}
#endif

template <>
inline TypeRef Type::CreateSimple<float>() {
return TypeRef(new Type(Float32));
Expand Down
Loading
Loading