diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index e7da5111..e64b8406 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -5,18 +5,6 @@ on: branches: [ master ] pull_request: branches: [ master ] - workflow_call: - inputs: - extra_cmake_flags: - required: false - type: string - extra_install: - required: false - type: string - gtest_filter: - required: false - type: string - default: "*" env: BUILD_TYPE: Release @@ -26,37 +14,41 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - build: [clang-6, gcc-7, gcc-8, gcc-9] + compiler: [clang-6, gcc-7, gcc-8, gcc-9] + ssl: [ssl_ON, ssl_OFF] include: - - build: clang-6 - os: ubuntu-latest + - compiler: clang-6 INSTALL: clang-6.0 C_COMPILER: clang-6.0 CXX_COMPILER: clang++-6.0 - - build: gcc-7 - os: ubuntu-latest + - compiler: gcc-7 INSTALL: gcc-7 g++-7 C_COMPILER: gcc-7 CXX_COMPILER: g++-7 - - build: gcc-8 - os: ubuntu-latest + - compiler: gcc-8 INSTALL: gcc-8 g++-8 C_COMPILER: gcc-8 CXX_COMPILER: g++-8 - - build: gcc-9 - os: ubuntu-latest + - compiler: gcc-9 INSTALL: gcc-9 g++-9 C_COMPILER: gcc-9 CXX_COMPILER: g++-9 + - ssl: ssl_ON + INSTALL_SSL: libssl-dev + EXTRA_CMAKE_FLAGS: -DWITH_OPENSSL=ON + + - ssl: ssl_OFF + EXTRA_CMAKE_FLAGS: -DWITH_OPENSSL=OFF + steps: - uses: actions/checkout@v2 - name: Install dependencies - run: sudo apt-get install -y cmake ${{ matrix.INSTALL }} ${{ inputs.extra_install }} + run: sudo apt-get install -y cmake ${{ matrix.INSTALL }} ${{ matrix.INSTALL_SSL }} - name: Configure CMake run: | @@ -65,7 +57,7 @@ jobs: -DCMAKE_CXX_COMPILER=${{ matrix.CXX_COMPILER}} \ -B ${{github.workspace}}/build \ -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DBUILD_TESTS=ON \ - ${{ inputs.extra_cmake_flags }} + ${{ matrix.EXTRA_CMAKE_FLAGS }} - name: Build run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --target all @@ -84,4 +76,4 @@ jobs: - name: Test working-directory: ${{github.workspace}}/build/ut - run: ./clickhouse-cpp-ut --gtest_filter="${{inputs.gtest_filter}}" + run: ./clickhouse-cpp-ut diff --git a/.github/workflows/linux_ssl.yml b/.github/workflows/linux_ssl.yml deleted file mode 100644 index 7d182b43..00000000 --- a/.github/workflows/linux_ssl.yml +++ /dev/null @@ -1,16 +0,0 @@ -name: Linux-ssl -# Almost the same as regular Linux builds, BUT with enabled SSL support, requires OpenSSL installed - -on: - push: - branches: [ master ] - pull_request: - branches: [ master ] - -jobs: - build-and-test: - uses: ClickHouse/clickhouse-cpp/.github/workflows/linux.yml@master - with: - extra_cmake_flags: -DWITH_OPENSSL=ON - extra_install: libssl-dev -# gtest_filter: "-*LocalhostTLS*" diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 134da3b7..a2bb171f 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -5,42 +5,54 @@ on: branches: [ master ] pull_request: branches: [ master ] - workflow_call: - inputs: - extra_cmake_flags: - required: false - type: string - extra_install: - required: false - type: string - gtest_filter: - required: false - type: string - default: "*" env: BUILD_TYPE: Release + CLICKHOUSE_USER: clickhouse_cpp_cicd + CLICKHOUSE_PASSWORD: clickhouse_cpp_cicd jobs: build: runs-on: macos-latest + strategy: + fail-fast: false + matrix: + build: [nossl, ssl] + include: + - build: nossl + extra_cmake_flags: -DWITH_OPENSSL=OFF + extra_install: + + - build: ssl + extra_cmake_flags: -DWITH_OPENSSL=ON -DOPENSSL_ROOT_DIR=/usr/local/opt/openssl/ + extra_install: openssl + steps: - uses: actions/checkout@v2 - name: Install dependencies - run: brew install cmake ${{inputs.extra_install}} + run: brew install cmake ${{matrix.extra_install}} - name: Configure CMake - run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DBUILD_TESTS=ON ${{inputs.extra_cmake_flags}} + run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DBUILD_TESTS=ON ${{matrix.extra_cmake_flags}} - name: Build run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --target all + - name: Start tls offoader proxy + # that mimics non-secure clickhouse running on localhost + # by tunneling queries to remote tls server + # (needed because we can't start real clickhouse instance on macOS) + run: | + wget https://github.com/filimonov/go-tlsoffloader/releases/download/v0.1.2/go-tlsoffloader_0.1.2_Darwin_x86_64.tar.gz + tar -xvzf go-tlsoffloader_0.1.2_Darwin_x86_64.tar.gz + ./go-tlsoffloader -l localhost:9000 -b github.demo.trial.altinity.cloud:9440 & + - name: Test working-directory: ${{github.workspace}}/build/ut env: # It is impossible to start CH server in docker on macOS due to github actions limitations, # so limit tests to ones that do no require server interaction. GTEST_FILTER_ONLY_LOCAL: "-Client/*" - run: ./clickhouse-cpp-ut --gtest_filter="${{inputs.gtest_filter}}:${{env.GTEST_FILTER_ONLY_LOCAL}}" + run: ./clickhouse-cpp-ut diff --git a/.github/workflows/macos_ssl.yml b/.github/workflows/macos_ssl.yml deleted file mode 100644 index 08a69272..00000000 --- a/.github/workflows/macos_ssl.yml +++ /dev/null @@ -1,17 +0,0 @@ -name: macOS-ssl -# Almost the same as regular macOS builds, BUT with enabled SSL support, requires OpenSSL installed via Homebrew (openssl@1.1) - -on: - push: - branches: [ master ] - pull_request: - branches: [ master ] - -jobs: - build-and-test: - uses: ClickHouse/clickhouse-cpp/.github/workflows/macos.yml@master - with: - extra_cmake_flags: -DWITH_OPENSSL=ON -DOPENSSL_ROOT_DIR=/usr/local/opt/openssl/ - extra_install: openssl - # There is no CH server running locally, so disable tests that try to connect to it. - gtest_filter: "-*Client*:*Local*:*ColumnPerformanceTest*" diff --git a/bench/bench.cpp b/bench/bench.cpp index 9ca8ff7b..4078e3f2 100644 --- a/bench/bench.cpp +++ b/bench/bench.cpp @@ -5,7 +5,11 @@ namespace clickhouse { Client g_client(ClientOptions() - .SetHost("localhost") + .SetHost( getEnvOrDefault("CLICKHOUSE_HOST", "localhost")) + .SetPort( std::stoi(getEnvOrDefault("CLICKHOUSE_PORT", "9000"))) + .SetUser( getEnvOrDefault("CLICKHOUSE_USER", "default")) + .SetPassword( getEnvOrDefault("CLICKHOUSE_PASSWORD", "")) + .SetDefaultDatabase(getEnvOrDefault("CLICKHOUSE_DB", "default")) .SetPingBeforeQuery(false)); static void SelectNumber(benchmark::State& state) { diff --git a/clickhouse/base/socket.cpp b/clickhouse/base/socket.cpp index 703b0e5a..b00e3207 100644 --- a/clickhouse/base/socket.cpp +++ b/clickhouse/base/socket.cpp @@ -18,6 +18,7 @@ #endif namespace clickhouse { + namespace { class LocalNames : public std::unordered_set { diff --git a/tests/simple/CMakeLists.txt b/tests/simple/CMakeLists.txt index 56c791dd..ad5d44e4 100644 --- a/tests/simple/CMakeLists.txt +++ b/tests/simple/CMakeLists.txt @@ -6,3 +6,10 @@ TARGET_LINK_LIBRARIES (simple-test clickhouse-cpp-lib ) +IF (CMAKE_CXX_COMPILER_ID STREQUAL "Clang") + # there is a problem with __builtin_mul_overflow call at link time + # the error looks like: ... undefined reference to `__muloti4' ... + # caused by clang bug https://bugs.llvm.org/show_bug.cgi?id=16404 + # explicit linking to compiler-rt allows to workaround the problem + set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --rtlib=compiler-rt") +ENDIF () diff --git a/tests/simple/main.cpp b/tests/simple/main.cpp index 41855514..10fb353d 100644 --- a/tests/simple/main.cpp +++ b/tests/simple/main.cpp @@ -13,6 +13,12 @@ using namespace clickhouse; using namespace std; +std::string getEnvOrDefault(const std::string& env, const std::string& default_val) +{ + const char* v = std::getenv(env.c_str()); + return v ? v : default_val; +} + inline void PrintBlock(const Block& block) { for (Block::Iterator bi(block); bi.IsValid(); bi.Next()) { std::cout << bi.Name() << " "; @@ -29,7 +35,7 @@ inline void ArrayExample(Client& client) { Block b; /// Create a table. - client.Execute("CREATE TABLE IF NOT EXISTS test.array (arr Array(UInt64)) ENGINE = Memory"); + client.Execute("CREATE TEMPORARY TABLE IF NOT EXISTS test_array (arr Array(UInt64))"); auto arr = std::make_shared(std::make_shared()); @@ -47,9 +53,9 @@ inline void ArrayExample(Client& client) { arr->AppendAsColumn(id); b.AppendColumn("arr", arr); - client.Insert("test.array", b); + client.Insert("test_array", b); - client.Select("SELECT arr FROM test.array", [](const Block& block) + client.Select("SELECT arr FROM test_array", [](const Block& block) { for (size_t c = 0; c < block.GetRowCount(); ++c) { auto col = block[0]->As()->GetAsColumn(c); @@ -62,14 +68,14 @@ inline void ArrayExample(Client& client) { ); /// Delete table. - client.Execute("DROP TABLE test.array"); + client.Execute("DROP TEMPORARY TABLE test_array"); } inline void MultiArrayExample(Client& client) { Block b; /// Create a table. - client.Execute("CREATE TABLE IF NOT EXISTS test.multiarray (arr Array(Array(UInt64))) ENGINE = Memory"); + client.Execute("CREATE TEMPORARY TABLE IF NOT EXISTS test_multiarray (arr Array(Array(UInt64)))"); auto arr = std::make_shared(std::make_shared()); @@ -80,9 +86,9 @@ inline void MultiArrayExample(Client& client) { auto a2 = std::make_shared(std::make_shared(std::make_shared())); a2->AppendAsColumn(arr); b.AppendColumn("arr", a2); - client.Insert("test.multiarray", b); + client.Insert("test_multiarray", b); - client.Select("SELECT arr FROM test.multiarray", [](const Block& block) + client.Select("SELECT arr FROM test_multiarray", [](const Block& block) { for (size_t c = 0; c < block.GetRowCount(); ++c) { auto col = block[0]->As()->GetAsColumn(c); @@ -102,14 +108,14 @@ inline void MultiArrayExample(Client& client) { ); /// Delete table. - client.Execute("DROP TABLE test.multiarray"); + client.Execute("DROP TEMPORARY TABLE test_multiarray"); } inline void DateExample(Client& client) { Block b; /// Create a table. - client.Execute("CREATE TABLE IF NOT EXISTS test.date (d DateTime, dz DateTime('Europe/Moscow')) ENGINE = Memory"); + client.Execute("CREATE TEMPORARY TABLE IF NOT EXISTS test_date (d DateTime, dz DateTime('Europe/Moscow'))"); auto d = std::make_shared(); auto dz = std::make_shared(); @@ -117,9 +123,9 @@ inline void DateExample(Client& client) { dz->Append(std::time(nullptr)); b.AppendColumn("d", d); b.AppendColumn("dz", dz); - client.Insert("test.date", b); + client.Insert("test_date", b); - client.Select("SELECT d, dz FROM test.date", [](const Block& block) + client.Select("SELECT d, dz FROM test_date", [](const Block& block) { for (size_t c = 0; c < block.GetRowCount(); ++c) { @@ -136,21 +142,22 @@ inline void DateExample(Client& client) { ); /// Delete table. - client.Execute("DROP TABLE test.date"); + client.Execute("DROP TEMPORARY TABLE test_date"); } inline void DateTime64Example(Client& client) { Block b; /// Create a table. - client.Execute("CREATE TABLE IF NOT EXISTS test.datetime64 (dt64 DateTime64(6)) ENGINE = Memory"); + client.Execute("CREATE TEMPORARY TABLE IF NOT EXISTS test_datetime64 (dt64 DateTime64(6))"); auto d = std::make_shared(6); d->Append(std::time(nullptr) * 1000000 + 123456); - b.AppendColumn("d", d); - client.Insert("test.datetime64", b); - client.Select("SELECT d FROM test.date", [](const Block& block) + b.AppendColumn("dt64", d); + client.Insert("test_datetime64", b); + + client.Select("SELECT dt64 FROM test_datetime64", [](const Block& block) { for (size_t c = 0; c < block.GetRowCount(); ++c) { auto col = block[0]->As(); @@ -165,21 +172,21 @@ inline void DateTime64Example(Client& client) { ); /// Delete table. - client.Execute("DROP TABLE test.datetime64"); + client.Execute("DROP TEMPORARY TABLE test_datetime64"); } inline void DecimalExample(Client& client) { Block b; /// Create a table. - client.Execute("CREATE TABLE IF NOT EXISTS test.decimal (d Decimal64(4)) ENGINE = Memory"); + client.Execute("CREATE TEMPORARY TABLE IF NOT EXISTS test_decimal (d Decimal64(4))"); auto d = std::make_shared(18, 4); d->Append(21111); b.AppendColumn("d", d); - client.Insert("test.decimal", b); + client.Insert("test_decimal", b); - client.Select("SELECT d FROM test.decimal", [](const Block& block) + client.Select("SELECT d FROM test_decimal", [](const Block& block) { for (size_t c = 0; c < block.GetRowCount(); ++c) { auto col = block[0]->As(); @@ -198,12 +205,12 @@ inline void DecimalExample(Client& client) { ); /// Delete table. - client.Execute("DROP TABLE test.decimal"); + client.Execute("DROP TEMPORARY TABLE test_decimal"); } inline void GenericExample(Client& client) { /// Create a table. - client.Execute("CREATE TABLE IF NOT EXISTS test.client (id UInt64, name String) ENGINE = Memory"); + client.Execute("CREATE TEMPORARY TABLE IF NOT EXISTS test_client (id UInt64, name String)"); /// Insert some values. { @@ -220,23 +227,23 @@ inline void GenericExample(Client& client) { block.AppendColumn("id" , id); block.AppendColumn("name", name); - client.Insert("test.client", block); + client.Insert("test_client", block); } /// Select values inserted in the previous step. - client.Select("SELECT id, name FROM test.client", [](const Block& block) + client.Select("SELECT id, name FROM test_client", [](const Block& block) { PrintBlock(block); } ); /// Delete table. - client.Execute("DROP TABLE test.client"); + client.Execute("DROP TEMPORARY TABLE test_client"); } inline void NullableExample(Client& client) { /// Create a table. - client.Execute("CREATE TABLE IF NOT EXISTS test.client (id Nullable(UInt64), date Nullable(Date)) ENGINE = Memory"); + client.Execute("CREATE TEMPORARY TABLE IF NOT EXISTS test_client (id Nullable(UInt64), date Nullable(Date))"); /// Insert some values. { @@ -266,11 +273,11 @@ inline void NullableExample(Client& client) { block.AppendColumn("date", std::make_shared(date, nulls)); } - client.Insert("test.client", block); + client.Insert("test_client", block); } /// Select values inserted in the previous step. - client.Select("SELECT id, date FROM test.client", [](const Block& block) + client.Select("SELECT id, date FROM test_client", [](const Block& block) { for (size_t c = 0; c < block.GetRowCount(); ++c) { auto col_id = block[0]->As(); @@ -295,7 +302,7 @@ inline void NullableExample(Client& client) { ); /// Delete table. - client.Execute("DROP TABLE test.client"); + client.Execute("DROP TEMPORARY TABLE test_client"); } inline void NumbersExample(Client& client) { @@ -320,7 +327,7 @@ inline void NumbersExample(Client& client) { inline void CancelableExample(Client& client) { /// Create a table. - client.Execute("CREATE TABLE IF NOT EXISTS test.client (x UInt64) ENGINE = Memory"); + client.Execute("CREATE TEMPORARY TABLE IF NOT EXISTS test_client (x UInt64)"); /// Insert a few blocks. for (unsigned j = 0; j < 10; j++) { @@ -332,28 +339,28 @@ inline void CancelableExample(Client& client) { } b.AppendColumn("x", x); - client.Insert("test.client", b); + client.Insert("test_client", b); } /// Send a query which is canceled after receiving the first block (note: /// due to the low number of rows in this test, this will not actually have /// any effect, it just tests for errors) - client.SelectCancelable("SELECT * FROM test.client", [](const Block&) + client.SelectCancelable("SELECT * FROM test_client", [](const Block&) { return false; } ); /// Delete table. - client.Execute("DROP TABLE test.client"); + client.Execute("DROP TEMPORARY TABLE test_client"); } inline void ExecptionExample(Client& client) { /// Create a table. - client.Execute("CREATE TABLE IF NOT EXISTS test.exceptions (id UInt64, name String) ENGINE = Memory"); + client.Execute("CREATE TEMPORARY TABLE IF NOT EXISTS test_exceptions (id UInt64, name String)"); /// Expect failing on table creation. try { - client.Execute("CREATE TABLE test.exceptions (id UInt64, name String) ENGINE = Memory"); + client.Execute("CREATE TEMPORARY TABLE test_exceptions (id UInt64, name String)"); } catch (const ServerException& e) { if (e.GetCode() == ErrorCodes::TABLE_ALREADY_EXISTS) { // OK @@ -363,12 +370,12 @@ inline void ExecptionExample(Client& client) { } /// Delete table. - client.Execute("DROP TABLE test.exceptions"); + client.Execute("DROP TEMPORARY TABLE test_exceptions"); } inline void EnumExample(Client& client) { /// Create a table. - client.Execute("CREATE TABLE IF NOT EXISTS test.enums (id UInt64, e Enum8('One' = 1, 'Two' = 2)) ENGINE = Memory"); + client.Execute("CREATE TEMPORARY TABLE IF NOT EXISTS test_enums (id UInt64, e Enum8('One' = 1, 'Two' = 2))"); /// Insert some values. { @@ -385,11 +392,11 @@ inline void EnumExample(Client& client) { block.AppendColumn("id", id); block.AppendColumn("e", e); - client.Insert("test.enums", block); + client.Insert("test_enums", block); } /// Select values inserted in the previous step. - client.Select("SELECT id, e FROM test.enums", [](const Block& block) + client.Select("SELECT id, e FROM test_enums", [](const Block& block) { for (Block::Iterator bi(block); bi.IsValid(); bi.Next()) { std::cout << bi.Name() << " "; @@ -404,7 +411,7 @@ inline void EnumExample(Client& client) { ); /// Delete table. - client.Execute("DROP TABLE test.enums"); + client.Execute("DROP TEMPORARY TABLE test_enums"); } inline void SelectNull(Client& client) { @@ -429,7 +436,7 @@ inline void ShowTables(Client& client) { inline void IPExample(Client &client) { /// Create a table. - client.Execute("CREATE TABLE IF NOT EXISTS test.ips (id UInt64, v4 IPv4, v6 IPv6) ENGINE = Memory"); + client.Execute("CREATE TEMPORARY TABLE IF NOT EXISTS test_ips (id UInt64, v4 IPv4, v6 IPv6)"); /// Insert some values. { @@ -454,11 +461,11 @@ inline void IPExample(Client &client) { block.AppendColumn("v4", v4); block.AppendColumn("v6", v6); - client.Insert("test.ips", block); + client.Insert("test_ips", block); } /// Select values inserted in the previous step. - client.Select("SELECT id, v4, v6 FROM test.ips", [](const Block& block) + client.Select("SELECT id, v4, v6 FROM test_ips", [](const Block& block) { for (Block::Iterator bi(block); bi.IsValid(); bi.Next()) { std::cout << bi.Name() << " "; @@ -474,7 +481,7 @@ inline void IPExample(Client &client) { ); /// Delete table. - client.Execute("DROP TABLE test.ips"); + client.Execute("DROP TEMPORARY TABLE test_ips"); } static void RunTests(Client& client) { @@ -498,14 +505,22 @@ int main() { try { { Client client(ClientOptions() - .SetHost("localhost") + .SetHost( getEnvOrDefault("CLICKHOUSE_HOST", "localhost")) + .SetPort( std::stoi(getEnvOrDefault("CLICKHOUSE_PORT", "9000"))) + .SetUser( getEnvOrDefault("CLICKHOUSE_USER", "default")) + .SetPassword( getEnvOrDefault("CLICKHOUSE_PASSWORD", "")) + .SetDefaultDatabase(getEnvOrDefault("CLICKHOUSE_DB", "default")) .SetPingBeforeQuery(true)); RunTests(client); } { Client client(ClientOptions() - .SetHost("localhost") + .SetHost( getEnvOrDefault("CLICKHOUSE_HOST", "localhost")) + .SetPort( std::stoi(getEnvOrDefault("CLICKHOUSE_PORT", "9000"))) + .SetUser( getEnvOrDefault("CLICKHOUSE_USER", "default")) + .SetPassword( getEnvOrDefault("CLICKHOUSE_PASSWORD", "")) + .SetDefaultDatabase(getEnvOrDefault("CLICKHOUSE_DB", "default")) .SetPingBeforeQuery(true) .SetCompressionMethod(CompressionMethod::LZ4)); RunTests(client); diff --git a/ut/CMakeLists.txt b/ut/CMakeLists.txt index 9e4289d4..5cc125b1 100644 --- a/ut/CMakeLists.txt +++ b/ut/CMakeLists.txt @@ -28,3 +28,6 @@ TARGET_LINK_LIBRARIES (clickhouse-cpp-ut clickhouse-cpp-lib gtest-lib ) +IF (CMAKE_CXX_COMPILER_ID STREQUAL "Clang") + set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --rtlib=compiler-rt") +ENDIF () diff --git a/ut/client_ut.cpp b/ut/client_ut.cpp index e798a8a5..792dd4af 100644 --- a/ut/client_ut.cpp +++ b/ut/client_ut.cpp @@ -1,6 +1,7 @@ #include #include "readonly_client_test.h" #include "connection_failed_client_test.h" +#include "utils.h" #include #include @@ -51,12 +52,12 @@ class ClientCase : public testing::TestWithParam { protected: void SetUp() override { client_ = std::make_unique(GetParam()); - client_->Execute("CREATE DATABASE IF NOT EXISTS test_clickhouse_cpp"); + // client_->Execute("CREATE DATABASE IF NOT EXISTS test_clickhouse_cpp"); } void TearDown() override { - if (client_) - client_->Execute("DROP DATABASE test_clickhouse_cpp"); + //if (client_) + // client_->Execute("DROP DATABASE test_clickhouse_cpp"); } template @@ -65,9 +66,8 @@ class ClientCase : public testing::TestWithParam { auto col = std::make_shared(); const auto type_name = col->GetType().GetName(); - client_->Execute("DROP TABLE IF EXISTS " + table_name + ";"); - client_->Execute("CREATE TABLE IF NOT EXISTS " + table_name + "( " + column_name + " " + type_name + " )" - "ENGINE = Memory"); + client_->Execute("DROP TEMPORARY TABLE IF EXISTS " + table_name + ";"); + client_->Execute("CREATE TEMPORARY TABLE IF NOT EXISTS " + table_name + "( " + column_name + " " + type_name + " )"); block.AppendColumn("test_column", col); @@ -80,7 +80,7 @@ class ClientCase : public testing::TestWithParam { } std::unique_ptr client_; - const std::string table_name = "test_clickhouse_cpp.test_ut_table"; + const std::string table_name = "test_clickhouse_cpp_test_ut_table"; const std::string column_name = "test_column"; }; @@ -88,9 +88,7 @@ TEST_P(ClientCase, Array) { Block b; /// Create a table. - client_->Execute( - "CREATE TABLE IF NOT EXISTS test_clickhouse_cpp.array (arr Array(UInt64)) " - "ENGINE = Memory"); + client_->Execute("CREATE TEMPORARY TABLE IF NOT EXISTS test_clickhouse_cpp_array (arr Array(UInt64)) "); /// Insert some values. { @@ -110,13 +108,13 @@ TEST_P(ClientCase, Array) { arr->AppendAsColumn(id); b.AppendColumn("arr", arr); - client_->Insert("test_clickhouse_cpp.array", b); + client_->Insert("test_clickhouse_cpp_array", b); } const uint64_t ARR_SIZE[] = { 1, 2, 3, 4 }; const uint64_t VALUE[] = { 1, 3, 7, 9 }; size_t row = 0; - client_->Select("SELECT arr FROM test_clickhouse_cpp.array", + client_->Select("SELECT arr FROM test_clickhouse_cpp_array", [ARR_SIZE, VALUE, &row](const Block& block) { if (block.GetRowCount() == 0) { @@ -141,16 +139,15 @@ TEST_P(ClientCase, Date) { /// Create a table. client_->Execute( - "CREATE TABLE IF NOT EXISTS test_clickhouse_cpp.date (d DateTime('UTC')) " - "ENGINE = Memory"); + "CREATE TEMPORARY TABLE IF NOT EXISTS test_clickhouse_cpp_date (d DateTime('UTC')) "); auto d = std::make_shared(); auto const now = std::time(nullptr); d->Append(now); b.AppendColumn("d", d); - client_->Insert("test_clickhouse_cpp.date", b); + client_->Insert("test_clickhouse_cpp_date", b); - client_->Select("SELECT d FROM test_clickhouse_cpp.date", [&now](const Block& block) + client_->Select("SELECT d FROM test_clickhouse_cpp_date", [&now](const Block& block) { if (block.GetRowCount() == 0) { return; @@ -247,14 +244,13 @@ TEST_P(ClientCase, LowCardinalityString_AsString) { options.SetBakcwardCompatibilityFeatureLowCardinalityAsWrappedColumn(true); client_ = std::make_unique(GetParam()); - client_->Execute("CREATE DATABASE IF NOT EXISTS test_clickhouse_cpp"); + // client_->Execute("CREATE DATABASE IF NOT EXISTS test_clickhouse_cpp"); Block block; auto col = std::make_shared(); - client_->Execute("DROP TABLE IF EXISTS " + table_name + ";"); - client_->Execute("CREATE TABLE IF NOT EXISTS " + table_name + "( " + column_name + " LowCardinality(String) )" - "ENGINE = Memory"); + client_->Execute("DROP TEMPORARY TABLE IF EXISTS " + table_name + ";"); + client_->Execute("CREATE TEMPORARY TABLE IF NOT EXISTS " + table_name + "( " + column_name + " LowCardinality(String) )"); block.AppendColumn("test_column", col); @@ -289,8 +285,7 @@ TEST_P(ClientCase, LowCardinalityString_AsString) { TEST_P(ClientCase, Generic) { client_->Execute( - "CREATE TABLE IF NOT EXISTS test_clickhouse_cpp.client (id UInt64, name String) " - "ENGINE = Memory"); + "CREATE TEMPORARY TABLE IF NOT EXISTS test_clickhouse_cpp_client (id UInt64, name String) "); const struct { uint64_t id; @@ -316,12 +311,12 @@ TEST_P(ClientCase, Generic) { block.AppendColumn("id" , id); block.AppendColumn("name", name); - client_->Insert("test_clickhouse_cpp.client", block); + client_->Insert("test_clickhouse_cpp_client", block); } /// Select values inserted in the previous step. size_t row = 0; - client_->Select("SELECT id, name FROM test_clickhouse_cpp.client", [TEST_DATA, &row](const Block& block) + client_->Select("SELECT id, name FROM test_clickhouse_cpp_client", [TEST_DATA, &row](const Block& block) { if (block.GetRowCount() == 0) { return; @@ -340,8 +335,7 @@ TEST_P(ClientCase, Generic) { TEST_P(ClientCase, Nullable) { /// Create a table. client_->Execute( - "CREATE TABLE IF NOT EXISTS test_clickhouse_cpp.nullable (id Nullable(UInt64), date Nullable(Date)) " - "ENGINE = Memory"); + "CREATE TEMPORARY TABLE IF NOT EXISTS test_clickhouse_cpp_nullable (id Nullable(UInt64), date Nullable(Date)) "); // Round std::time_t to start of date. const std::time_t cur_date = std::time(nullptr) / 86400 * 86400; @@ -380,12 +374,12 @@ TEST_P(ClientCase, Nullable) { block.AppendColumn("date", std::make_shared(date, nulls)); } - client_->Insert("test_clickhouse_cpp.nullable", block); + client_->Insert("test_clickhouse_cpp_nullable", block); } /// Select values inserted in the previous step. size_t row = 0; - client_->Select("SELECT id, date FROM test_clickhouse_cpp.nullable", + client_->Select("SELECT id, date FROM test_clickhouse_cpp_nullable", [TEST_DATA, &row](const Block& block) { for (size_t c = 0; c < block.GetRowCount(); ++c, ++row) { @@ -439,16 +433,15 @@ TEST_P(ClientCase, SimpleAggregateFunction) { return; } - client_->Execute("DROP TABLE IF EXISTS test_clickhouse_cpp.SimpleAggregateFunction"); + client_->Execute("DROP TEMPORARY TABLE IF EXISTS test_clickhouse_cpp_SimpleAggregateFunction"); client_->Execute( - "CREATE TABLE IF NOT EXISTS test_clickhouse_cpp.SimpleAggregateFunction (saf SimpleAggregateFunction(sum, UInt64))" - "ENGINE = Memory"); + "CREATE TEMPORARY TABLE IF NOT EXISTS test_clickhouse_cpp_SimpleAggregateFunction (saf SimpleAggregateFunction(sum, UInt64))"); constexpr size_t EXPECTED_ROWS = 10; - client_->Execute("INSERT INTO test_clickhouse_cpp.SimpleAggregateFunction (saf) SELECT number FROM system.numbers LIMIT 10"); + client_->Execute("INSERT INTO test_clickhouse_cpp_SimpleAggregateFunction (saf) SELECT number FROM system.numbers LIMIT 10"); size_t total_rows = 0; - client_->Select("Select * FROM test_clickhouse_cpp.SimpleAggregateFunction", [&total_rows](const Block & block) { + client_->Select("Select * FROM test_clickhouse_cpp_SimpleAggregateFunction", [&total_rows](const Block & block) { if (block.GetRowCount() == 0) return; @@ -469,8 +462,7 @@ TEST_P(ClientCase, SimpleAggregateFunction) { TEST_P(ClientCase, Cancellable) { /// Create a table. client_->Execute( - "CREATE TABLE IF NOT EXISTS test_clickhouse_cpp.cancel (x UInt64) " - "ENGINE = Memory"); + "CREATE TEMPORARY TABLE IF NOT EXISTS test_clickhouse_cpp_cancel (x UInt64) "); /// Insert a few blocks. In order to make cancel have effect, we have to /// insert a relative larget amount of data. @@ -485,13 +477,13 @@ TEST_P(ClientCase, Cancellable) { } b.AppendColumn("x", x); - client_->Insert("test_clickhouse_cpp.cancel", b); + client_->Insert("test_clickhouse_cpp_cancel", b); } /// Send a query which is canceled after receiving the first blockr. int row_cnt = 0; EXPECT_NO_THROW( - client_->SelectCancelable("SELECT * FROM test_clickhouse_cpp.cancel", + client_->SelectCancelable("SELECT * FROM test_clickhouse_cpp_cancel", [&row_cnt](const Block& block) { row_cnt += block.GetRowCount(); @@ -506,22 +498,19 @@ TEST_P(ClientCase, Cancellable) { TEST_P(ClientCase, Exception) { /// Create a table. client_->Execute( - "CREATE TABLE IF NOT EXISTS test_clickhouse_cpp.exceptions (id UInt64, name String) " - "ENGINE = Memory"); + "CREATE TEMPORARY TABLE IF NOT EXISTS test_clickhouse_cpp_exceptions (id UInt64, name String) "); /// Expect failing on table creation. EXPECT_THROW( client_->Execute( - "CREATE TABLE test_clickhouse_cpp.exceptions (id UInt64, name String) " - "ENGINE = Memory"), + "CREATE TEMPORARY TABLE test_clickhouse_cpp_exceptions (id UInt64, name String) "), ServerException); } TEST_P(ClientCase, Enum) { /// Create a table. client_->Execute( - "CREATE TABLE IF NOT EXISTS test_clickhouse_cpp.enums (id UInt64, e Enum8('One' = 1, 'Two' = 2)) " - "ENGINE = Memory"); + "CREATE TEMPORARY TABLE IF NOT EXISTS test_clickhouse_cpp_enums (id UInt64, e Enum8('One' = 1, 'Two' = 2)) "); const struct { uint64_t id; @@ -554,12 +543,12 @@ TEST_P(ClientCase, Enum) { block.AppendColumn("id", id); block.AppendColumn("e", e); - client_->Insert("test_clickhouse_cpp.enums", block); + client_->Insert("test_clickhouse_cpp_enums", block); } /// Select values inserted in the previous step. size_t row = 0; - client_->Select("SELECT id, e FROM test_clickhouse_cpp.enums", [&row, TEST_DATA](const Block& block) + client_->Select("SELECT id, e FROM test_clickhouse_cpp_enums", [&row, TEST_DATA](const Block& block) { if (block.GetRowCount() == 0) { return; @@ -579,10 +568,9 @@ TEST_P(ClientCase, Enum) { TEST_P(ClientCase, Decimal) { client_->Execute( - "CREATE TABLE IF NOT EXISTS " - "test_clickhouse_cpp.decimal (id UInt64, d1 Decimal(9, 4), d2 Decimal(18, 9), d3 Decimal(38, 19), " - " d4 Decimal32(4), d5 Decimal64(9), d6 Decimal128(19)) " - "ENGINE = Memory"); + "CREATE TEMPORARY TABLE IF NOT EXISTS " + "test_clickhouse_cpp_decimal (id UInt64, d1 Decimal(9, 4), d2 Decimal(18, 9), d3 Decimal(38, 19), " + " d4 Decimal32(4), d5 Decimal64(9), d6 Decimal128(19)) "); { Block b; @@ -678,10 +666,10 @@ TEST_P(ClientCase, Decimal) { b.AppendColumn("d5", d5); b.AppendColumn("d6", d6); - client_->Insert("test_clickhouse_cpp.decimal", b); + client_->Insert("test_clickhouse_cpp_decimal", b); } - client_->Select("SELECT id, d1, d2, d3, d4, d5, d6 FROM test_clickhouse_cpp.decimal ORDER BY id", [](const Block& b) { + client_->Select("SELECT id, d1, d2, d3, d4, d5, d6 FROM test_clickhouse_cpp_decimal ORDER BY id", [](const Block& b) { if (b.GetRowCount() == 0) { return; } @@ -768,9 +756,9 @@ TEST_P(ClientCase, Decimal) { // Test special chars in names TEST_P(ClientCase, ColEscapeNameTest) { - client_->Execute(R"sql(DROP TABLE IF EXISTS test_clickhouse_cpp."col_escape_""name_test";)sql"); + client_->Execute(R"sql(DROP TEMPORARY TABLE IF EXISTS "test_clickhouse_cpp_col_escape_""name_test";)sql"); - client_->Execute(R"sql(CREATE TABLE IF NOT EXISTS test_clickhouse_cpp."col_escape_""name_test" ("test space" UInt64, "test "" quote" UInt64, "test ""`'[]&_\ all" UInt64) ENGINE = Memory)sql"); + client_->Execute(R"sql(CREATE TEMPORARY TABLE IF NOT EXISTS "test_clickhouse_cpp_col_escape_""name_test" ("test space" UInt64, "test "" quote" UInt64, "test ""`'[]&_\ all" UInt64))sql"); auto col1 = std::make_shared(); col1->Append(1); @@ -794,8 +782,8 @@ TEST_P(ClientCase, ColEscapeNameTest) { block.AppendColumn(column_names[1], col2); block.AppendColumn(column_names[2], col3); - client_->Insert(R"sql(test_clickhouse_cpp."col_escape_""name_test")sql", block); - client_->Select(R"sql(SELECT * FROM test_clickhouse_cpp."col_escape_""name_test")sql", [] (const Block& sblock) + client_->Insert(R"sql("test_clickhouse_cpp_col_escape_""name_test")sql", block); + client_->Select(R"sql(SELECT * FROM "test_clickhouse_cpp_col_escape_""name_test")sql", [] (const Block& sblock) { int row = sblock.GetRowCount(); if (row <= 0) {return;} @@ -823,18 +811,17 @@ TEST_P(ClientCase, DateTime64) { } Block block; - client_->Execute("DROP TABLE IF EXISTS test_clickhouse_cpp.datetime64;"); + client_->Execute("DROP TEMPORARY TABLE IF EXISTS test_clickhouse_cpp_datetime64;"); - client_->Execute("CREATE TABLE IF NOT EXISTS " - "test_clickhouse_cpp.datetime64 (dt DateTime64(6)) " - "ENGINE = Memory"); + client_->Execute("CREATE TEMPORARY TABLE IF NOT EXISTS " + "test_clickhouse_cpp_datetime64 (dt DateTime64(6)) "); auto col_dt64 = std::make_shared(6); block.AppendColumn("dt", col_dt64); // Empty INSERT and SELECT - client_->Insert("test_clickhouse_cpp.datetime64", block); - client_->Select("SELECT dt FROM test_clickhouse_cpp.datetime64", + client_->Insert("test_clickhouse_cpp_datetime64", block); + client_->Select("SELECT dt FROM test_clickhouse_cpp_datetime64", [](const Block& block) { ASSERT_EQ(0U, block.GetRowCount()); } @@ -856,10 +843,10 @@ TEST_P(ClientCase, DateTime64) { block.RefreshRowCount(); // Non-empty INSERT and SELECT - client_->Insert("test_clickhouse_cpp.datetime64", block); + client_->Insert("test_clickhouse_cpp_datetime64", block); size_t total_rows = 0; - client_->Select("SELECT dt FROM test_clickhouse_cpp.datetime64", + client_->Select("SELECT dt FROM test_clickhouse_cpp_datetime64", [&total_rows, &data](const Block& block) { total_rows += block.GetRowCount(); if (block.GetRowCount() == 0) { @@ -883,10 +870,51 @@ INSTANTIATE_TEST_SUITE_P( Client, ClientCase, ::testing::Values( ClientOptions() - .SetHost("localhost") + .SetHost( getEnvOrDefault("CLICKHOUSE_HOST", "localhost")) + .SetPort( std::stoi(getEnvOrDefault("CLICKHOUSE_PORT", "9000"))) + .SetUser( getEnvOrDefault("CLICKHOUSE_USER", "default")) + .SetPassword( getEnvOrDefault("CLICKHOUSE_PASSWORD", "")) + .SetDefaultDatabase(getEnvOrDefault("CLICKHOUSE_DB", "default")) .SetPingBeforeQuery(true), ClientOptions() - .SetHost("localhost") + .SetHost( getEnvOrDefault("CLICKHOUSE_HOST", "localhost")) + .SetPort( std::stoi(getEnvOrDefault("CLICKHOUSE_PORT", "9000"))) + .SetUser( getEnvOrDefault("CLICKHOUSE_USER", "default")) + .SetPassword( getEnvOrDefault("CLICKHOUSE_PASSWORD", "")) + .SetDefaultDatabase(getEnvOrDefault("CLICKHOUSE_DB", "default")) .SetPingBeforeQuery(false) .SetCompressionMethod(CompressionMethod::LZ4) )); + +namespace { +using namespace clickhouse; + +const auto QUERIES = std::vector{"SELECT version()", "SELECT fqdn()", "SELECT buildId()", + "SELECT uptime()", "SELECT filesystemFree()", "SELECT now()"}; +} + +INSTANTIATE_TEST_SUITE_P(ClientLocalReadonly, ReadonlyClientTest, + ::testing::Values(ReadonlyClientTest::ParamType{ + ClientOptions() + .SetHost( getEnvOrDefault("CLICKHOUSE_HOST", "localhost")) + .SetPort( std::stoi(getEnvOrDefault("CLICKHOUSE_PORT", "9000"))) + .SetUser( getEnvOrDefault("CLICKHOUSE_USER", "default")) + .SetPassword( getEnvOrDefault("CLICKHOUSE_PASSWORD", "")) + .SetDefaultDatabase(getEnvOrDefault("CLICKHOUSE_DB", "default")) + .SetSendRetries(1) + .SetPingBeforeQuery(true) + .SetCompressionMethod(CompressionMethod::None), + QUERIES})); + +INSTANTIATE_TEST_SUITE_P(ClientLocalFailed, ConnectionFailedClientTest, + ::testing::Values(ConnectionFailedClientTest::ParamType{ + ClientOptions() + .SetHost( getEnvOrDefault("CLICKHOUSE_HOST", "localhost")) + .SetPort( std::stoi(getEnvOrDefault("CLICKHOUSE_PORT", "9000"))) + .SetUser("non_existing_user_clickhouse_cpp_test") + .SetPassword("wrongpwd") + .SetDefaultDatabase(getEnvOrDefault("CLICKHOUSE_DB", "default")) + .SetSendRetries(1) + .SetPingBeforeQuery(true) + .SetCompressionMethod(CompressionMethod::None), + "Authentication failed: password is incorrect"})); diff --git a/ut/performance_tests.cpp b/ut/performance_tests.cpp index 2f3c8ef0..f6883f35 100644 --- a/ut/performance_tests.cpp +++ b/ut/performance_tests.cpp @@ -167,14 +167,20 @@ TYPED_TEST_P(ColumnPerformanceTest, InsertAndSelect) { using ColumnType = TypeParam; using Timer = Timer; - const std::string table_name = "PerformanceTests.ColumnTest"; + const std::string table_name = "PerformanceTests_ColumnTest"; const std::string column_name = "column"; auto column = InstantiateColumn(); - Client client(ClientOptions().SetHost("localhost")); - client.Execute("CREATE DATABASE IF NOT EXISTS PerformanceTests"); - client.Execute("DROP TABLE IF EXISTS PerformanceTests.ColumnTest"); - client.Execute("CREATE TABLE PerformanceTests.ColumnTest (" + column_name + " " + column.Type()->GetName() + ") ENGINE = Memory"); + Client client(ClientOptions() + .SetHost( getEnvOrDefault("CLICKHOUSE_HOST", "localhost")) + .SetPort( std::stoi(getEnvOrDefault("CLICKHOUSE_PORT", "9000"))) + .SetUser( getEnvOrDefault("CLICKHOUSE_USER", "default")) + .SetPassword( getEnvOrDefault("CLICKHOUSE_PASSWORD", "")) + .SetDefaultDatabase(getEnvOrDefault("CLICKHOUSE_DB", "default")) + ); + // client.Execute("CREATE DATABASE IF NOT EXISTS PerformanceTests"); + client.Execute("DROP TEMPORARY TABLE IF EXISTS PerformanceTests_ColumnTest"); + client.Execute("CREATE TEMPORARY TABLE PerformanceTests_ColumnTest (" + column_name + " " + column.Type()->GetName() + ")"); const size_t ITEMS_COUNT = 1'000'000; @@ -209,7 +215,7 @@ TYPED_TEST_P(ColumnPerformanceTest, InsertAndSelect) { size_t total_rows = 0; Timer timer; Timer::DurationType inner_loop_duration{0}; - client.Select("SELECT " + column_name + " FROM " + table_name, [&total_rows, &inner_loop_duration](const Block & block) { + client.Select("SELECT " + column_name + " FROM " + table_name, [&](const Block & block) { Timer timer; total_rows += block.GetRowCount(); if (block.GetRowCount() == 0) { diff --git a/ut/ssl_ut.cpp b/ut/ssl_ut.cpp index 212ac849..4f410c2f 100644 --- a/ut/ssl_ut.cpp +++ b/ut/ssl_ut.cpp @@ -2,6 +2,7 @@ */ #include "readonly_client_test.h" #include "connection_failed_client_test.h" +#include "utils.h" #include #include @@ -33,11 +34,11 @@ INSTANTIATE_TEST_SUITE_P( RemoteTLS, ReadonlyClientTest, ::testing::Values(ReadonlyClientTest::ParamType { ClientOptions() - .SetHost("github.demo.trial.altinity.cloud") - .SetPort(9440) - .SetUser("demo") - .SetPassword("demo") - .SetDefaultDatabase("default") + .SetHost( getEnvOrDefault("CLICKHOUSE_SECURE_HOST", "github.demo.trial.altinity.cloud")) + .SetPort( std::stoi(getEnvOrDefault("CLICKHOUSE_SECURE_PORT", "9440"))) + .SetUser( getEnvOrDefault("CLICKHOUSE_SECURE_USER", "demo")) + .SetPassword( getEnvOrDefault("CLICKHOUSE_SECURE_PASSWORD", "demo")) + .SetDefaultDatabase(getEnvOrDefault("CLICKHOUSE_SECURE_DB", "default")) .SetSendRetries(1) .SetPingBeforeQuery(true) .SetCompressionMethod(CompressionMethod::None) @@ -51,9 +52,11 @@ INSTANTIATE_TEST_SUITE_P( Remote_GH_API_TLS, ReadonlyClientTest, ::testing::Values(ReadonlyClientTest::ParamType { ClientOptions() - .SetHost("gh-api.clickhouse.tech") - .SetPort(9440) - .SetUser("explorer") + .SetHost( getEnvOrDefault("CLICKHOUSE_SECURE2_HOST", "gh-api.clickhouse.tech")) + .SetPort( std::stoi(getEnvOrDefault("CLICKHOUSE_SECURE2_PORT", "9440"))) + .SetUser( getEnvOrDefault("CLICKHOUSE_SECURE2_USER", "explorer")) + .SetPassword( getEnvOrDefault("CLICKHOUSE_SECURE2_PASSWORD", "")) + .SetDefaultDatabase(getEnvOrDefault("CLICKHOUSE_SECURE2_DB", "default")) .SetSendRetries(1) .SetPingBeforeQuery(true) .SetCompressionMethod(CompressionMethod::None) @@ -67,9 +70,11 @@ INSTANTIATE_TEST_SUITE_P( Remote_GH_API_TLS_no_CA, ConnectionFailedClientTest, ::testing::Values(ConnectionFailedClientTest::ParamType { ClientOptions() - .SetHost("gh-api.clickhouse.tech") - .SetPort(9440) - .SetUser("explorer") + .SetHost( getEnvOrDefault("CLICKHOUSE_SECURE2_HOST", "gh-api.clickhouse.tech")) + .SetPort( std::stoi(getEnvOrDefault("CLICKHOUSE_SECURE2_PORT", "9440"))) + .SetUser( getEnvOrDefault("CLICKHOUSE_SECURE2_USER", "explorer")) + .SetPassword( getEnvOrDefault("CLICKHOUSE_SECURE2_PASSWORD", "")) + .SetDefaultDatabase(getEnvOrDefault("CLICKHOUSE_SECURE2_DB", "default")) .SetSendRetries(1) .SetPingBeforeQuery(true) .SetCompressionMethod(CompressionMethod::None) @@ -83,9 +88,11 @@ INSTANTIATE_TEST_SUITE_P( Remote_GH_API_TLS_wrong_TLS_version, ConnectionFailedClientTest, ::testing::Values(ConnectionFailedClientTest::ParamType { ClientOptions() - .SetHost("gh-api.clickhouse.tech") - .SetPort(9440) - .SetUser("explorer") + .SetHost( getEnvOrDefault("CLICKHOUSE_SECURE2_HOST", "gh-api.clickhouse.tech")) + .SetPort( std::stoi(getEnvOrDefault("CLICKHOUSE_SECURE2_PORT", "9440"))) + .SetUser( getEnvOrDefault("CLICKHOUSE_SECURE2_USER", "explorer")) + .SetPassword( getEnvOrDefault("CLICKHOUSE_SECURE2_PASSWORD", "")) + .SetDefaultDatabase(getEnvOrDefault("CLICKHOUSE_SECURE2_DB", "default")) .SetSendRetries(1) .SetPingBeforeQuery(true) .SetCompressionMethod(CompressionMethod::None) diff --git a/ut/utils.cpp b/ut/utils.cpp index a3f0ca21..8e5c351d 100644 --- a/ut/utils.cpp +++ b/ut/utils.cpp @@ -91,3 +91,9 @@ std::ostream& operator<<(std::ostream & ostr, const Block & block) { return ostr; } + +std::string getEnvOrDefault(const std::string& env, const std::string& default_val) +{ + const char* v = std::getenv(env.c_str()); + return v ? v : default_val; +} diff --git a/ut/utils.h b/ut/utils.h index 2dc81b1a..0bde2c73 100644 --- a/ut/utils.h +++ b/ut/utils.h @@ -106,3 +106,5 @@ MeasuresCollector collect(MeasureFunc && f) } std::ostream& operator<<(std::ostream & ostr, const clickhouse::Block & block); + +std::string getEnvOrDefault(const std::string& env, const std::string& default_val);