#include #include "utils.h" #include "roundtrip_column.h" #include #include #include using namespace clickhouse; // Use value-parameterized tests to run same tests with different client // options. class RoundtripCase : public testing::TestWithParam { protected: void SetUp() override { client_ = std::make_unique(GetParam()); } void TearDown() override { client_.reset(); } std::string GetSettingValue(const std::string& name) { std::string result; client_->Select("SELECT value FROM system.settings WHERE name = \'" + name + "\'", [&result](const Block& block) { if (block.GetRowCount() == 0) { return; } result = block[0]->AsStrict()->At(0); } ); return result; } std::unique_ptr client_; }; TEST_P(RoundtripCase, ArrayTUint64) { auto array = std::make_shared>(); array->Append({0, 1, 2}); auto result = RoundtripColumnValues(*client_, array)->AsStrict(); auto row = result->GetAsColumn(0)->As(); EXPECT_EQ(0u, row->At(0)); EXPECT_EQ(1u, (*row)[1]); EXPECT_EQ(2u, (*row)[2]); } TEST_P(RoundtripCase, ArrayTArrayTUint64) { const std::vector> row_values = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9, 10} }; auto array = std::make_shared>>(); array->Append(row_values); auto result_typed = ColumnArrayT>::Wrap(RoundtripColumnValues(*client_, array)); EXPECT_TRUE(CompareRecursive(*array, *result_typed)); } TEST_P(RoundtripCase, ArrayTArrayTArrayTUint64) { using ColumnType = ColumnArrayT>>; const std::vector>> row_values = { {{1, 2, 3}, {3, 2, 1}}, {{4, 5, 6}, {6, 5, 4}}, {{7, 8, 9, 10}, {}}, {{}, {10, 9, 8, 7}} }; auto array = std::make_shared(); array->Append(row_values); auto result_typed = ColumnType::Wrap(RoundtripColumnValues(*client_, array)); EXPECT_TRUE(CompareRecursive(*array, *result_typed)); } TEST_P(RoundtripCase, ArrayTFixedString) { auto array = std::make_shared>(6); array->Append({"hello", "world"}); auto result_typed = ColumnArrayT::Wrap(RoundtripColumnValues(*client_, array)); EXPECT_TRUE(CompareRecursive(*array, *result_typed)); } TEST_P(RoundtripCase, ArrayTString) { auto array = std::make_shared>(); array->Append({"hello", "world"}); auto result_typed = ColumnArrayT::Wrap(RoundtripColumnValues(*client_, array)); EXPECT_TRUE(CompareRecursive(*array, *result_typed)); } TEST_P(RoundtripCase, MapTUint64String) { using Map = ColumnMapT; auto map = std::make_shared(std::make_shared(), std::make_shared()); std::map row; row[1] = "hello"; row[2] = "world"; map->Append(row); auto result_typed = Map::Wrap(RoundtripColumnValues(*client_, map)); EXPECT_TRUE(CompareRecursive(*map, *result_typed)); } TEST_P(RoundtripCase, MapUUID_Tuple_String_Array_Uint64) { using Tuple = ColumnTupleT>; using Map = ColumnMapT; auto map = std::make_shared(std::make_shared(), std::make_shared( std::make_tuple(std::make_shared(), std::make_shared>()))); std::map>> row; row[UUID{1, 1}] = std::make_tuple("hello", std::vector{1, 2, 3}) ; row[UUID{2, 2}] = std::make_tuple("world", std::vector{4, 5, 6}) ; map->Append(row); auto result_typed = Map::Wrap(RoundtripColumnValues(*client_, map)); EXPECT_TRUE(CompareRecursive(*map, *result_typed)); } TEST_P(RoundtripCase, Point) { if (GetSettingValue("allow_experimental_geo_types") != "1") { GTEST_SKIP() << "Test is skipped because experimental geo types are not allowed. Set setting allow_experimental_geo_types = 1 in order to allow it." << std::endl; } auto col = std::make_shared(); col->Append({1.0, 2.0}); col->Append({0.1, 0.2}); auto result_typed = RoundtripColumnValues(*client_, col)->AsStrict(); EXPECT_TRUE(CompareRecursive(*col, *result_typed)); } TEST_P(RoundtripCase, Ring) { if (GetSettingValue("allow_experimental_geo_types") != "1") { GTEST_SKIP() << "Test is skipped because experimental geo types are not allowed. Set setting allow_experimental_geo_types = 1 in order to allow it." << std::endl; } auto col = std::make_shared(); { std::vector ring{{1.0, 2.0}, {3.0, 4.0}}; col->Append(ring); } { std::vector ring{{0.1, 0.2}, {0.3, 0.4}}; col->Append(ring); } auto result_typed = RoundtripColumnValues(*client_, col)->AsStrict(); EXPECT_TRUE(CompareRecursive(*col, *result_typed)); } TEST_P(RoundtripCase, Polygon) { if (GetSettingValue("allow_experimental_geo_types") != "1") { GTEST_SKIP() << "Test is skipped because experimental geo types are not allowed. Set setting allow_experimental_geo_types = 1 in order to allow it." << std::endl; } auto col = std::make_shared(); { std::vector> polygon {{{1.0, 2.0}, {3.0, 4.0}}, {{5.0, 6.0}, {7.0, 8.0}}}; col->Append(polygon); } { std::vector> polygon {{{0.1, 0.2}, {0.3, 0.4}}, {{0.5, 0.6}, {0.7, 0.8}}}; col->Append(polygon); } auto result_typed = RoundtripColumnValues(*client_, col)->AsStrict(); EXPECT_TRUE(CompareRecursive(*col, *result_typed)); } TEST_P(RoundtripCase, MultiPolygon) { if (GetSettingValue("allow_experimental_geo_types") != "1") { GTEST_SKIP() << "Test is skipped because experimental geo types are not allowed. Set setting allow_experimental_geo_types = 1 in order to allow it." << std::endl; } auto col = std::make_shared(); { std::vector>> multi_polygon {{{{1.0, 2.0}, {3.0, 4.0}}, {{5.0, 6.0}, {7.0, 8.0}}}, {{{1.1, 2.2}, {3.3, 4.4}}, {{5.5, 6.6}, {7.7, 8.8}}}}; col->Append(multi_polygon); } { std::vector>> multi_polygon {{{{0.1, 0.2}, {0.3, 0.4}}, {{0.5, 0.6}, {0.7, 0.8}}}, {{{1.1, 1.2}, {1.3, 1.4}}, {{1.5, 1.6}, {1.7, 1.8}}}}; col->Append(multi_polygon); } auto result_typed = RoundtripColumnValues(*client_, col)->AsStrict(); EXPECT_TRUE(CompareRecursive(*col, *result_typed)); } TEST_P(RoundtripCase, LowCardinalityTString) { using TestColumn = ColumnLowCardinalityT; auto col = std::make_shared(); col->Append("abc"); col->Append("def"); col->Append("abc"); col->Append("abc"); auto result_typed = RoundtripColumnValues(*client_, col)->As(); EXPECT_TRUE(CompareRecursive(*col, *result_typed)); } TEST_P(RoundtripCase, LowCardinalityTNullableString) { using TestColumn = ColumnLowCardinalityT>; auto col = std::make_shared(); col->Append("abc"); col->Append("def"); col->Append("abc"); col->Append(std::nullopt); col->Append("abc"); col->Append(std::nullopt); col->Append(std::nullopt); col->Append("foobar"); auto result_typed = RoundtripColumnValues(*client_, col)->As(); EXPECT_TRUE(CompareRecursive(*col, *result_typed)); } TEST_P(RoundtripCase, ArrayTNullableString) { using TestColumn = ColumnArrayT>; auto col = std::make_shared(); col->Append({std::nullopt, std::nullopt, std::nullopt}); col->Append(std::vector>{"abc", std::nullopt}); auto result_typed = RoundtripColumnValues(*client_, col)->As(); EXPECT_TRUE(CompareRecursive(*col, *result_typed)); } TEST_P(RoundtripCase, TupleTNullableString) { using TestColumn = ColumnTupleT>; auto col = std::make_shared(std::make_tuple(std::make_shared>())); col->Append(std::make_tuple(std::nullopt)); col->Append(std::make_tuple("abc")); auto result_typed = RoundtripColumnValues(*client_, col)->As(); EXPECT_TRUE(CompareRecursive(*col, *result_typed)); } TEST_P(RoundtripCase, Map_TString_TNullableString) { using Key = ColumnString; using Value = ColumnNullableT; using TestColumn = ColumnMapT; auto col = std::make_shared(std::make_shared(), std::make_shared()); { std::map> value; value["1"] = "one"; value["2"] = std::nullopt; col->Append(value); } { std::map> value; value["4"] = "one"; value["2"] = std::nullopt; col->Append(value); } auto result_typed = RoundtripColumnValues(*client_, col)->As(); EXPECT_TRUE(CompareRecursive(*col, *result_typed)); } TEST_P(RoundtripCase, Map_LowCardinalityTString_LowCardinalityTNullableString) { using Key = ColumnLowCardinalityT; using Value = ColumnLowCardinalityT>; using TestColumn = ColumnMapT; auto col = std::make_shared(std::make_shared(), std::make_shared()); { std::map> value; value["1"] = "one"; value["2"] = std::nullopt; col->Append(value); } { std::map> value; value["4"] = "one"; value["2"] = std::nullopt; col->Append(value); } auto result_typed = RoundtripColumnValues(*client_, col)->As(); EXPECT_TRUE(CompareRecursive(*col, *result_typed)); } TEST_P(RoundtripCase, RoundtripArrayLowCardinalityTString) { using TestColumn = ColumnArrayT>; auto array = std::make_shared(); array->Append(std::vector{}); array->Append(std::vector{}); auto result_typed = RoundtripColumnValues(*client_, array)->As(); EXPECT_TRUE(CompareRecursive(*array, *result_typed)); } const auto LocalHostEndpoint = ClientOptions() .SetHost( getEnvOrDefault("CLICKHOUSE_HOST", "localhost")) .SetPort( getEnvOrDefault("CLICKHOUSE_PORT", "9000")) .SetUser( getEnvOrDefault("CLICKHOUSE_USER", "default")) .SetPassword( getEnvOrDefault("CLICKHOUSE_PASSWORD", "")) .SetDefaultDatabase(getEnvOrDefault("CLICKHOUSE_DB", "default")); INSTANTIATE_TEST_SUITE_P( Roundtrip, RoundtripCase, ::testing::Values( ClientOptions(LocalHostEndpoint) .SetPingBeforeQuery(true) .SetBakcwardCompatibilityFeatureLowCardinalityAsWrappedColumn(false), ClientOptions(LocalHostEndpoint) .SetPingBeforeQuery(false) .SetCompressionMethod(CompressionMethod::LZ4) .SetBakcwardCompatibilityFeatureLowCardinalityAsWrappedColumn(false), ClientOptions(LocalHostEndpoint) .SetPingBeforeQuery(false) .SetCompressionMethod(CompressionMethod::ZSTD) .SetBakcwardCompatibilityFeatureLowCardinalityAsWrappedColumn(false) ));