diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index 4b79fd84..8dde1cd8 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -98,6 +98,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}} \ diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 1fc91061..8deea625 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -48,6 +48,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}} \ diff --git a/.github/workflows/windows_mingw.yml b/.github/workflows/windows_mingw.yml index 0567527b..f5699d8f 100644 --- a/.github/workflows/windows_mingw.yml +++ b/.github/workflows/windows_mingw.yml @@ -52,7 +52,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. diff --git a/.github/workflows/windows_msvc.yml b/.github/workflows/windows_msvc.yml index 12695dd5..16208211 100644 --- a/.github/workflows/windows_msvc.yml +++ b/.github/workflows/windows_msvc.yml @@ -28,7 +28,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}} diff --git a/CMakeLists.txt b/CMakeLists.txt index 2eab3e7f..dfa7ccba 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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}" diff --git a/README.md b/README.md index 43282e54..5d398a7e 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,7 @@ C++ client for [ClickHouse](https://clickhouse.com/). ## Supported data types * Array(T) +* Bool \* (by default, mapped to UInt8 when receiving data) * Date * DateTime, DateTime64 * DateTime([timezone]), DateTime64(N, [timezone]) @@ -25,6 +26,13 @@ C++ client for [ClickHouse](https://clickhouse.com/). * Point, Ring, Polygon, MultiPolygon * JSON - experimental support; requires output_format_native_write_json_as_string=1; data is passed as strings +\*: There exists a distinct `ColumnBool` and entry in the `Type` enumeration that +can be used. +By default, data received from the server will map Bool columns to UInt8. This is +a backwards compatibility feature. +If you want the library to produce ColumnBool, set the CMake variable `DCH_MAP_BOOL_TO_UINT8=OFF`. +The default for this variable will switch, with it being subsequently removed, in +a future release. ## Dependencies In the most basic case one needs only: @@ -258,5 +266,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 ``` - - diff --git a/clickhouse/CMakeLists.txt b/clickhouse/CMakeLists.txt index c759dfcb..7b68fb6e 100644 --- a/clickhouse/CMakeLists.txt +++ b/clickhouse/CMakeLists.txt @@ -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 @@ -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 @@ -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) diff --git a/clickhouse/client.h b/clickhouse/client.h index 17e1e404..a55fd748 100644 --- a/clickhouse/client.h +++ b/clickhouse/client.h @@ -20,6 +20,7 @@ #include "columns/tuple.h" #include "columns/time.h" #include "columns/uuid.h" +#include "columns/bool.h" #include #include diff --git a/clickhouse/columns/bool.cpp b/clickhouse/columns/bool.cpp new file mode 100644 index 00000000..c9cd8719 --- /dev/null +++ b/clickhouse/columns/bool.cpp @@ -0,0 +1,79 @@ +#include "bool.h" + +#include "../types/types.h" + +namespace clickhouse { + +ColumnBool::ColumnBool() + : Column(Type::CreateSimple()) + , data_() +{ +} + +ColumnBool::ColumnBool(std::vector data) + : Column(Type::CreateSimple()) + , data_(std::move(data)) +{ +} + +void ColumnBool::Reserve(size_t new_cap) { + data_.Reserve(new_cap); +} + +size_t ColumnBool::Capacity() const { + return data_.Capacity(); +} + +void ColumnBool::Append(bool value) { + data_.Append(static_cast(value)); +} + +bool ColumnBool::At(size_t n) const { + return static_cast(data_.At(n)); +} + +void ColumnBool::Append(ColumnRef column) { + if (auto col = column->As()) { + auto& src = col->data_.GetWritableData(); + data_.GetWritableData().insert(data_.GetWritableData().end(), src.begin(), src.end()); + } else if (auto col = column->As()) { + 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(data_.Slice(begin, len)); + return std::make_shared(std::move(sliced->GetWritableData())); +} + +ColumnRef ColumnBool::CloneEmpty() const { + return std::make_shared(); +} + +void ColumnBool::Swap(Column& other) { + auto& col = dynamic_cast(other); + data_.Swap(col.data_); +} + +ItemView ColumnBool::GetItem(size_t index) const { + return ItemView{Type::Bool, data_.At(index)}; +} + +} // namespace clickhouse diff --git a/clickhouse/columns/bool.h b/clickhouse/columns/bool.h new file mode 100644 index 00000000..5ba42bab --- /dev/null +++ b/clickhouse/columns/bool.h @@ -0,0 +1,62 @@ +#pragma once + +#include "column.h" +#include "numeric.h" + +#include "../types/types.h" + +#include + +namespace clickhouse { + +class ColumnBool : public Column { +public: + using ValueType = bool; + + ColumnBool(); + explicit ColumnBool(std::vector 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); } + + /// Returns the capacity of the column + size_t Capacity() const; + +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 diff --git a/clickhouse/columns/factory.cpp b/clickhouse/columns/factory.cpp index 399551ee..a01304f8 100644 --- a/clickhouse/columns/factory.cpp +++ b/clickhouse/columns/factory.cpp @@ -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 @@ -50,6 +51,8 @@ static ColumnRef CreateTerminalColumn(const TypeAst& ast) { case Type::Void: return std::make_shared(); + case Type::Bool: + return std::make_shared(); case Type::UInt8: return std::make_shared(); case Type::UInt16: diff --git a/clickhouse/columns/itemview.cpp b/clickhouse/columns/itemview.cpp index 610db030..c34ac5b0 100644 --- a/clickhouse/columns/itemview.cpp +++ b/clickhouse/columns/itemview.cpp @@ -44,6 +44,7 @@ void ItemView::ValidateData(Type::Code type, DataType data) { case Type::Code::Int8: case Type::Code::UInt8: case Type::Code::Enum8: + case Type::Code::Bool: return AssertSize({1}); case Type::Code::Int16: diff --git a/clickhouse/columns/itemview.h b/clickhouse/columns/itemview.h index 199994b6..0fd7428d 100644 --- a/clickhouse/columns/itemview.h +++ b/clickhouse/columns/itemview.h @@ -28,7 +28,9 @@ struct ItemView { inline auto ConvertToStorageValue(const T& t) { if constexpr (std::is_same_v || std::is_same_v) { return std::string_view{t}; - } else if constexpr (std::is_fundamental_v || std::is_same_v> || std::is_same_v>) { + } else if constexpr (std::is_fundamental_v + || std::is_same_v> + || std::is_same_v>) { return std::string_view{reinterpret_cast(&t), sizeof(T)}; } else { static_assert(!std::is_same_v, "Unknown type, which can't be stored in ItemView"); @@ -65,7 +67,9 @@ struct ItemView { using ValueType = std::remove_cv_t>; if constexpr (std::is_same_v || std::is_same_v) { return data; - } else if constexpr (std::is_fundamental_v || std::is_same_v || std::is_same_v) { + } else if constexpr (std::is_fundamental_v + || std::is_same_v + || std::is_same_v) { if (sizeof(ValueType) == data.size()) { return *reinterpret_cast(data.data()); } else { diff --git a/clickhouse/types/type_parser.cpp b/clickhouse/types/type_parser.cpp index 3c60c03e..82492412 100644 --- a/clickhouse/types/type_parser.cpp +++ b/clickhouse/types/type_parser.cpp @@ -34,7 +34,11 @@ static const std::unordered_map 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 }, diff --git a/clickhouse/types/types.cpp b/clickhouse/types/types.cpp index 4435133e..e12342c8 100644 --- a/clickhouse/types/types.cpp +++ b/clickhouse/types/types.cpp @@ -55,6 +55,7 @@ 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"; + case Type::Code::Bool: return "Bool"; } return "Unknown type"; @@ -87,6 +88,7 @@ std::string Type::GetName() const { case Polygon: case MultiPolygon: case JSON: + case Bool: return TypeName(code_); case Time64: return As()->GetName(); @@ -149,6 +151,7 @@ uint64_t Type::GetTypeUniqueId() const { case Ring: case Polygon: case MultiPolygon: + case Bool: // For simple types, unique ID is the same as Type::Code return code_; diff --git a/clickhouse/types/types.h b/clickhouse/types/types.h index 9cdaa99d..5a2fa53e 100644 --- a/clickhouse/types/types.h +++ b/clickhouse/types/types.h @@ -60,6 +60,7 @@ class Type { Time, Time64, JSON, + Bool, }; using EnumItem = std::pair; @@ -394,6 +395,11 @@ inline TypeRef Type::CreateSimple() { return TypeRef(new Type(UInt64)); } +template <> +inline TypeRef Type::CreateSimple() { + return TypeRef(new Type(Bool)); +} + template <> inline TypeRef Type::CreateSimple() { return TypeRef(new Type(Float32)); diff --git a/ut/Column_ut.cpp b/ut/Column_ut.cpp index 78852831..c0fdc1ac 100644 --- a/ut/Column_ut.cpp +++ b/ut/Column_ut.cpp @@ -193,6 +193,10 @@ using TestCases = ::testing::Types< NumberColumnTestCase, NumberColumnTestCase, +#if !CH_MAP_BOOL_TO_UINT8 + GenericColumnTestCase, uint8_t, &MakeBools>, +#endif + GenericColumnTestCase, std::string, &MakeStrings>, GenericColumnTestCase, std::string, &MakeFixedStrings<12>>, GenericColumnTestCase, std::string, &MakeJSONs>, diff --git a/ut/CreateColumnByType_ut.cpp b/ut/CreateColumnByType_ut.cpp index c00e4bad..e312c116 100644 --- a/ut/CreateColumnByType_ut.cpp +++ b/ut/CreateColumnByType_ut.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -63,7 +64,15 @@ class CreateColumnByTypeWithName : public ::testing::TestWithParamGetType().GetName(), "UInt8"); + EXPECT_EQ(col->GetType().GetCode(), Type::UInt8); + EXPECT_NE(nullptr, col->As()); +#else + EXPECT_EQ(col->GetType().GetName(), "Bool"); + EXPECT_EQ(col->GetType().GetCode(), Type::Bool); + EXPECT_NE(nullptr, col->As()); +#endif } TEST_P(CreateColumnByTypeWithName, CreateColumnByType) @@ -79,6 +88,9 @@ INSTANTIATE_TEST_SUITE_P(Basic, CreateColumnByTypeWithName, ::testing::Values( "String", "Date", "DateTime", "UUID", "Int128", "UInt128" )); +#if !CH_MAP_BOOL_TO_UINT8 +INSTANTIATE_TEST_SUITE_P(BasicBool, CreateColumnByTypeWithName, ::testing::Values("Bool")); +#endif INSTANTIATE_TEST_SUITE_P(Parametrized, CreateColumnByTypeWithName, ::testing::Values( "FixedString(0)", "FixedString(10000)", diff --git a/ut/client_ut.cpp b/ut/client_ut.cpp index 5449c6af..3b6b2d5c 100644 --- a/ut/client_ut.cpp +++ b/ut/client_ut.cpp @@ -1,4 +1,5 @@ #include +#include #include "clickhouse/base/socket.h" #include "clickhouse/version.h" @@ -22,6 +23,22 @@ using namespace clickhouse; +#if CH_MAP_BOOL_TO_UINT8 +using ClientBoolColumn = ColumnUInt8; +using ClientBoolValue = uint8_t; +#else +using ClientBoolColumn = ColumnBool; +using ClientBoolValue = bool; +#endif + +ClientBoolValue MakeClientBoolValue(bool value) { +#if CH_MAP_BOOL_TO_UINT8 + return static_cast(value); +#else + return value; +#endif +} + template std::shared_ptr createTableWithOneColumn(Client & client, const std::string & table_name, const std::string & column_name) { @@ -400,11 +417,11 @@ TEST_P(ClientCase, Generic) { auto id = std::make_shared(); auto name = std::make_shared(); - auto f = std::make_shared (); + auto f = std::make_shared(); for (auto const& td : TEST_DATA) { id->Append(td.id); name->Append(td.name); - f->Append(td.f); + f->Append(MakeClientBoolValue(td.f)); } block.AppendColumn("id" , id); @@ -426,7 +443,7 @@ TEST_P(ClientCase, Generic) { for (size_t c = 0; c < block.GetRowCount(); ++c, ++row) { EXPECT_EQ(TEST_DATA[row].id, (*block[0]->As())[c]); EXPECT_EQ(TEST_DATA[row].name, (*block[1]->As())[c]); - EXPECT_EQ(TEST_DATA[row].f, (*block[2]->As())[c]); + EXPECT_EQ(MakeClientBoolValue(TEST_DATA[row].f), (*block[2]->As())[c]); } } ); @@ -468,13 +485,13 @@ TEST_P(ClientCase, InsertData) { // Fetch the derived columns. auto id = block[0]->As(); auto name = block[1]->As(); - auto f = block[2]->As(); + auto f = block[2]->As(); // Insert some values. for (auto const& td : TEST_DATA) { id->Append(td.id); name->Append(td.name); - f->Append(td.f); + f->Append(MakeClientBoolValue(td.f)); } block.RefreshRowCount(); client_->SendInsertBlock(block); @@ -484,7 +501,7 @@ TEST_P(ClientCase, InsertData) { for (auto const& td : TEST_DATA2) { id->Append(td.id); name->Append(td.name); - f->Append(td.f); + f->Append(MakeClientBoolValue(td.f)); } block.RefreshRowCount(); client_->SendInsertBlock(block); @@ -509,13 +526,13 @@ TEST_P(ClientCase, InsertData) { for (size_t c = 0; c < block.GetRowCount(); ++c, ++row) { EXPECT_EQ(TEST_DATA[row].id, (*block[0]->As())[c]); EXPECT_EQ(TEST_DATA[row].name, (*block[1]->As())[c]); - EXPECT_EQ(TEST_DATA[row].f, (*block[2]->As())[c]); + EXPECT_EQ(MakeClientBoolValue(TEST_DATA[row].f), (*block[2]->As())[c]); } } else { for (size_t c = 0; c < block.GetRowCount(); ++c, ++row) { EXPECT_EQ(TEST_DATA2[row-block_two_row_num].id, (*block[0]->As())[c]); EXPECT_EQ(TEST_DATA2[row-block_two_row_num].name, (*block[1]->As())[c]); - EXPECT_EQ(TEST_DATA2[row-block_two_row_num].f, (*block[2]->As())[c]); + EXPECT_EQ(MakeClientBoolValue(TEST_DATA2[row-block_two_row_num].f), (*block[2]->As())[c]); } } } diff --git a/ut/column_array_ut.cpp b/ut/column_array_ut.cpp index 2925eedf..887f5047 100644 --- a/ut/column_array_ut.cpp +++ b/ut/column_array_ut.cpp @@ -337,6 +337,19 @@ TEST(ColumnArrayT, Wrap_UInt64_2D) { EXPECT_TRUE(CompareRecursive(values, array)); } +TEST(ColumnArrayT, Bool) { + // Check inserting\reading back data from clickhouse::ColumnArrayT + + const std::vector> values = { + {1u, 0u, 0u}, + {0u, 1u, 1u, 0u, 1u, 0u}, + {0u}, + {}, + {1u, 0u} + }; + CreateAndTestColumnArrayT(values); +} + TEST(ColumnArrayT, left_value_no_move) { std::string value0 = "000000000000000000"; std::string value1 = "111111111111111111"; diff --git a/ut/columns_ut.cpp b/ut/columns_ut.cpp index 489067b8..3e931132 100644 --- a/ut/columns_ut.cpp +++ b/ut/columns_ut.cpp @@ -137,6 +137,27 @@ TEST(ColumnsCase, StringAppend) { ASSERT_EQ(col->At(2), "11"); } +TEST(ColumnsCase, BoolInit) +{ + auto values = MakeBools(); + auto col = std::make_shared(values); + + ASSERT_EQ(col->Size(), values.size()); + ASSERT_EQ(col->At(0), 1); + ASSERT_EQ(col->At(3), 0); +} + +TEST(ColumnsCase, BoolAppend) +{ + auto col = std::make_shared(); + col->Append(true); + col->Append(false); + + ASSERT_EQ(col->Size(), 2u); + ASSERT_EQ(col->At(0), true); + ASSERT_EQ(col->At(1), false); +} + TEST(ColumnsCase, JSONInit) { auto values = MakeJSONs(); auto col = std::make_shared(values); diff --git a/ut/itemview_ut.cpp b/ut/itemview_ut.cpp index a932a0b5..5c6b5b58 100644 --- a/ut/itemview_ut.cpp +++ b/ut/itemview_ut.cpp @@ -29,6 +29,11 @@ TEST(ItemView, StorableTypes) { TEST_ITEMVIEW_TYPE_VALUE(TypeCode, NativeType, std::numeric_limits::max() - 1); \ TEST_ITEMVIEW_TYPE_VALUE(TypeCode, NativeType, std::numeric_limits::max()); + TEST_ITEMVIEW_TYPE_VALUES(Type::Code::Bool, int8_t); + TEST_ITEMVIEW_TYPE_VALUES(Type::Code::Bool, bool); + TEST_ITEMVIEW_TYPE_VALUE(Type::Code::Bool, bool, false); + TEST_ITEMVIEW_TYPE_VALUE(Type::Code::Bool, bool, true); + TEST_ITEMVIEW_TYPE_VALUES(Type::Code::Int8, int8_t); TEST_ITEMVIEW_TYPE_VALUES(Type::Code::Int16, int16_t); TEST_ITEMVIEW_TYPE_VALUES(Type::Code::Int32, int32_t); diff --git a/ut/type_parser_ut.cpp b/ut/type_parser_ut.cpp index c538abdb..f593de2c 100644 --- a/ut/type_parser_ut.cpp +++ b/ut/type_parser_ut.cpp @@ -24,6 +24,19 @@ TEST(TypeParserCase, ParseFixedString) { ASSERT_EQ(ast.elements.front().value, 24U); } +TEST(TypeParserCase, ParseBool) { + TypeAst ast; + TypeParser("Bool").Parse(&ast); + + ASSERT_EQ(ast.meta, TypeAst::Terminal); + ASSERT_EQ(ast.name, "Bool"); +#if !CH_MAP_BOOL_TO_UINT8 + ASSERT_EQ(ast.code, Type::Bool); +#else + ASSERT_EQ(ast.code, Type::UInt8); +#endif +} + TEST(TypeParserCase, ParseJSON) { TypeAst ast; TypeParser("JSON").Parse(&ast); diff --git a/ut/types_ut.cpp b/ut/types_ut.cpp index b0029cd7..2a18241a 100644 --- a/ut/types_ut.cpp +++ b/ut/types_ut.cpp @@ -1,5 +1,7 @@ #include +#include #include +#include #include #include @@ -34,6 +36,8 @@ TEST(TypesCase, TypeName) { ); ASSERT_EQ(Type::CreateMap(Type::CreateSimple(), Type::CreateString())->GetName(), "Map(Int32, String)"); + + ASSERT_EQ(Type::CreateSimple()->GetName(), "Bool"); } TEST(TypesCase, NullableType) { @@ -140,6 +144,9 @@ TEST(TypesCase, DecimalTypes) { TEST(TypesCase, IsEqual) { const std::string type_names[] = { +#if !CH_MAP_BOOL_TO_UINT8 + "Bool", +#endif "UInt8", "Int8", // "UInt128", diff --git a/ut/utils.cpp b/ut/utils.cpp index 989f7a5c..f52b17cf 100644 --- a/ut/utils.cpp +++ b/ut/utils.cpp @@ -362,6 +362,9 @@ std::ostream& operator<<(std::ostream& ostr, const ItemView& item_view) { case Type::UInt8: ostr << static_cast(item_view.get()); break; + case Type::Bool: + ostr << (item_view.get() ? "true" : "false"); + break; case Type::UInt16: ostr << static_cast(item_view.get()); break; diff --git a/ut/utils_ut.cpp b/ut/utils_ut.cpp index e1de32fb..db8b887f 100644 --- a/ut/utils_ut.cpp +++ b/ut/utils_ut.cpp @@ -237,6 +237,8 @@ TEST(ItemView, OutputToOstream_VALID) { EXPECTED_SERIALIZATION("FixedString : \"string\" (6 bytes)", ColumnFixedString(6), "string"); EXPECTED_SERIALIZATION(R"(JSON : "{"key": "value"}" (16 bytes))", ColumnJSON(), R"({"key": "value"})"); + EXPECTED_SERIALIZATION("Bool : false", ColumnBool(), false); + EXPECTED_SERIALIZATION("Bool : true", ColumnBool(), true); EXPECTED_SERIALIZATION("Int8 : -123", ColumnInt8(), -123); EXPECTED_SERIALIZATION("Int16 : -1234", ColumnInt16(), -1234); EXPECTED_SERIALIZATION("Int32 : -12345", ColumnInt32(), -12345);