Skip to content
Merged
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
4 changes: 4 additions & 0 deletions BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,10 @@ cc_library(
# Users are free to include Abseil in their own projects and convert values produced by this
# library to the corresponding Abseil types.
"CH_USE_ABSEIL_FOR_BIGNUM=0",
# `Client::GetCurrentEndpoint()` returns `Endpoint` by value rather than the legacy
# `std::optional<Endpoint>`. The Bazel build does not promise backward compatibility with
# the 2.x API, so it always uses the new form (CMake's `CH_NON_OPTIONAL_CURRENT_ENDPOINT=ON`).
"CH_NON_OPTIONAL_CURRENT_ENDPOINT=1",
] + select({
# `WITH_OPENSSL` enables the TLS code paths in client.cpp /
# sslsocket.cpp (same macro as the CMake option). `USE_BORINGSSL`
Expand Down
29 changes: 27 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,40 @@ IF ("${CMAKE_CURRENT_SOURCE_DIR}" STREQUAL "${CMAKE_SOURCE_DIR}")
ENDIF ()
OPTION (WITH_OPENSSL "Use OpenSSL for TLS connections" OFF)

OPTION (CH_USE_ABSEIL_FOR_BIGNUM "Use Google Abseil for wide (128-bit) integers" ON)
OPTION (WITH_SYSTEM_ABSEIL "Use system Google Abseil, otherwise vendored part part of Google Abseil will be used" OFF)

OPTION (WITH_SYSTEM_LZ4 "Use system LZ4" OFF)
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)

# API compatibility options. The defaults preserve the legacy 2.x behaviour. CH_USE_3X_API switches
# all of them to the 3.x values at once; individual options may not be set to conflicting values.
OPTION (CH_USE_3X_API "Use the 3.x API: implies CH_MAP_BOOL_TO_UINT8=OFF, CH_USE_ABSEIL_FOR_BIGNUM=OFF, CH_NON_OPTIONAL_CURRENT_ENDPOINT=ON" OFF)
IF (CH_USE_3X_API)
SET (CH_3X_MAP_BOOL_TO_UINT8 OFF)
SET (CH_3X_USE_ABSEIL_FOR_BIGNUM OFF)
SET (CH_3X_NON_OPTIONAL_CURRENT_ENDPOINT ON)
ELSE ()
SET (CH_3X_MAP_BOOL_TO_UINT8 ON)
SET (CH_3X_USE_ABSEIL_FOR_BIGNUM ON)
SET (CH_3X_NON_OPTIONAL_CURRENT_ENDPOINT OFF)
ENDIF ()
OPTION (CH_MAP_BOOL_TO_UINT8 "Map ClickHouse Bool type to UInt8 instead of exposing a distinct Bool API." ${CH_3X_MAP_BOOL_TO_UINT8})
OPTION (CH_USE_ABSEIL_FOR_BIGNUM "Use Google Abseil for wide (128-bit) integers" ${CH_3X_USE_ABSEIL_FOR_BIGNUM})
OPTION (CH_NON_OPTIONAL_CURRENT_ENDPOINT "Make Client::GetCurrentEndpoint() return Endpoint by value instead of std::optional<Endpoint>." ${CH_3X_NON_OPTIONAL_CURRENT_ENDPOINT})

IF (CH_USE_3X_API)
FOREACH (opt MAP_BOOL_TO_UINT8 USE_ABSEIL_FOR_BIGNUM NON_OPTIONAL_CURRENT_ENDPOINT)
IF ((CH_${opt} AND NOT CH_3X_${opt}) OR (NOT CH_${opt} AND CH_3X_${opt}))
MESSAGE (FATAL_ERROR
"CH_USE_3X_API=ON requires CH_${opt}=${CH_3X_${opt}}, but it is set to '${CH_${opt}}'. "
"Either drop the explicit CH_${opt} setting, or set it to ${CH_3X_${opt}}. "
"If the value comes from a previous configure run, delete CMakeCache.txt or pass -DCH_${opt}=${CH_3X_${opt}}.")
ENDIF ()
ENDFOREACH ()
ENDIF ()

PROJECT (CLICKHOUSE-CLIENT
VERSION "${CLICKHOUSE_CPP_VERSION}"
Expand Down
27 changes: 18 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,25 @@ Here is an example with recommended settings;
```sh
$ mkdir build .
$ cd build
$ cmake .. -DCH_USE_ABSEIL_FOR_BIGNUM=NO -DCH_MAP_BOOL_TO_UINT8=NO
$ cmake .. -DCH_USE_3X_API=YES
$ make
```

The command above disables two legacy CMake defaults, `CH_USE_ABSEIL_FOR_BIGNUM` and
`CH_MAP_BOOL_TO_UINT8`. New projects should set both options to `OFF`. Existing projects can keep
the defaults temporarily, but should migrate to this configuration as this behavior will be removed
in the future versions of the library.
`CH_USE_3X_API` selects the new 3.x API. As the project evolves we bring new changes to the
API; sometimes these require breaking changes. When that happens we keep the old API
unchanged by default and hide the changes behind specific flags. To enable all of these changes
at once, we recommend enabling `CH_USE_3X_API`, which will be the default API in version 3.0.

Enabling this option is equivalent to setting the following individual options:

| Option | 2.x default | 3.x value | Effect when set to the 3.x value |
|------------------------------------|-------------|-----------|-----------------------------------------------------------------------------------------|
| `CH_MAP_BOOL_TO_UINT8` | `ON` | `OFF` | ClickHouse `Bool` maps to `clickhouse::ColumnBool` instead of `ColumnUInt8` |
| `CH_USE_ABSEIL_FOR_BIGNUM` | `ON` | `OFF` | 128-bit integers use the self-contained implementation instead of Abseil |
| `CH_NON_OPTIONAL_CURRENT_ENDPOINT` | `OFF` | `ON` | `Client::GetCurrentEndpoint()` returns `Endpoint` by value instead of `std::optional` |

The individual options can still be set one at a time for a gradual migration; however, when
`CH_USE_3X_API=ON` is given, setting any of them to a conflicting value is a configuration error.

Please refer to the workflows for the reference on dependencies/build options
- https://github.com/ClickHouse/clickhouse-cpp/blob/master/.github/workflows/linux.yml
Expand Down Expand Up @@ -97,8 +108,7 @@ Then include it from your `CMakeLists.txt`:
cmake_minimum_required(VERSION 3.13)
project(application-example LANGUAGES CXX)

set(CH_USE_ABSEIL_FOR_BIGNUM OFF)
set(CH_MAP_BOOL_TO_UINT8 OFF)
set(CH_USE_3X_API ON)

add_subdirectory(contrib/clickhouse-cpp)

Expand All @@ -116,8 +126,7 @@ project(application-example LANGUAGES CXX)

include(FetchContent)

set(CH_USE_ABSEIL_FOR_BIGNUM OFF)
set(CH_MAP_BOOL_TO_UINT8 OFF)
set(CH_USE_3X_API ON)

FetchContent_Declare(
clickhouse_cpp
Expand Down
5 changes: 5 additions & 0 deletions clickhouse/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,11 @@ ELSE ()
TARGET_COMPILE_DEFINITIONS (clickhouse-cpp-lib PUBLIC CH_USE_ABSEIL_FOR_BIGNUM=0)
ENDIF ()

IF (CH_NON_OPTIONAL_CURRENT_ENDPOINT)
TARGET_COMPILE_DEFINITIONS (clickhouse-cpp-lib PUBLIC CH_NON_OPTIONAL_CURRENT_ENDPOINT=1)
ELSE ()
TARGET_COMPILE_DEFINITIONS (clickhouse-cpp-lib PUBLIC CH_NON_OPTIONAL_CURRENT_ENDPOINT=0)
ENDIF ()

IF (NOT BUILD_SHARED_LIBS)
ADD_LIBRARY (clickhouse-cpp-lib-static ALIAS clickhouse-cpp-lib)
Expand Down
6 changes: 6 additions & 0 deletions clickhouse/client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1412,9 +1412,15 @@ void Client::ResetConnectionEndpoint() {
impl_->ResetConnectionEndpoint();
}

#if CH_NON_OPTIONAL_CURRENT_ENDPOINT
Endpoint Client::GetCurrentEndpoint() const {
return impl_->GetCurrentEndpoint().value();
}
#else
const std::optional<Endpoint>& Client::GetCurrentEndpoint() const {
return impl_->GetCurrentEndpoint();
}
#endif

const ServerInfo& Client::GetServerInfo() const {
return impl_->GetServerInfo();
Expand Down
4 changes: 4 additions & 0 deletions clickhouse/client.h
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,11 @@ class Client {

/// Get current endpoint, i.e. the last successfully connected endpoint.
/// It remains optional for backward compatibility, but now always contains a value.
#if CH_NON_OPTIONAL_CURRENT_ENDPOINT
Endpoint GetCurrentEndpoint() const;
#else
const std::optional<Endpoint>& GetCurrentEndpoint() const;
#endif
Comment on lines 341 to +347

/// Try to reconnect to different endpoints one by one only one time. If it doesn't work, throw
/// an exception. The function starts with the last successfully connected endpoint.
Expand Down
4 changes: 4 additions & 0 deletions contrib/absl/absl/base/options.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,12 @@
// Include a standard library header to allow configuration based on the
// standard library in use.
#ifdef __cplusplus
#if __cplusplus >= 202002L
#include <version>
#else
#include <ciso646>
#endif
#endif

// -----------------------------------------------------------------------------
// Type Compatibility Options
Expand Down
4 changes: 4 additions & 0 deletions tests/simple/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -588,7 +588,11 @@ int main() {
Client client(ClientOptions(localHostEndpoint)
.SetPingBeforeQuery(true));
RunTests(client);
#if CH_NON_OPTIONAL_CURRENT_ENDPOINT
std::cout << "current endpoint : " << client.GetCurrentEndpoint().host << "\n";
#else
std::cout << "current endpoint : " << client.GetCurrentEndpoint().value().host << "\n";
#endif
}

{
Expand Down
24 changes: 17 additions & 7 deletions ut/client_ut.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,16 @@ ClientBoolValue MakeClientBoolValue(bool value) {
#endif
}

// Client::GetCurrentEndpoint() returns either Endpoint or std::optional<Endpoint>
// depending on CH_NON_OPTIONAL_CURRENT_ENDPOINT; normalize to Endpoint for tests.
Endpoint CurrentEndpoint(const Client & client) {
#if CH_NON_OPTIONAL_CURRENT_ENDPOINT
return client.GetCurrentEndpoint();
#else
return client.GetCurrentEndpoint().value();
#endif
}

template <typename T>
std::shared_ptr<T> createTableWithOneColumn(Client & client, const std::string & table_name, const std::string & column_name)
{
Expand Down Expand Up @@ -1784,7 +1794,7 @@ TEST_P(ConnectionSuccessTestCase, SuccessConnectionEstablished) {

try {
client = std::make_unique<Client>(client_options);
auto endpoint = client->GetCurrentEndpoint().value();
auto endpoint = CurrentEndpoint(*client);
ASSERT_EQ("localhost", endpoint.host);
ASSERT_EQ(9000u, endpoint.port);
SUCCEED();
Expand Down Expand Up @@ -1866,27 +1876,27 @@ TEST(ResetConnectionEndpointTest, ReconnectsCurrentBeforeFailover) {

// The initial connection selects the first endpoint.
Client client(options, std::move(socket_factory));
ASSERT_EQ(primary, client.GetCurrentEndpoint().value());
ASSERT_EQ(primary, CurrentEndpoint(client));

// A healthy current endpoint is retried without advancing.
adapter->SetFailEndpoint(std::nullopt);
adapter->ClearConnectRequests();
client.ResetConnectionEndpoint();
EXPECT_EQ(primary, client.GetCurrentEndpoint().value());
EXPECT_EQ(primary, CurrentEndpoint(client));
EXPECT_EQ(std::vector<Endpoint>{primary}, adapter->ConnectRequests());

// Failure of the current endpoint advances to the next endpoint.
adapter->SetFailEndpoint(primary);
adapter->ClearConnectRequests();
client.ResetConnectionEndpoint();
EXPECT_EQ(secondary, client.GetCurrentEndpoint().value());
EXPECT_EQ(secondary, CurrentEndpoint(client));
EXPECT_EQ((std::vector<Endpoint>{primary, secondary}), adapter->ConnectRequests());

// Failure of the last endpoint wraps around to the first endpoint.
adapter->SetFailEndpoint(secondary);
adapter->ClearConnectRequests();
client.ResetConnectionEndpoint();
EXPECT_EQ(primary, client.GetCurrentEndpoint().value());
EXPECT_EQ(primary, CurrentEndpoint(client));
EXPECT_EQ((std::vector<Endpoint>{secondary, primary}), adapter->ConnectRequests());
}

Expand All @@ -1896,12 +1906,12 @@ TEST_P(ResetConnectionTestCase, ResetConnectionTest) {

try {
client = std::make_unique<Client>(client_options);
auto endpoint = client->GetCurrentEndpoint().value();
auto endpoint = CurrentEndpoint(*client);
ASSERT_EQ("localhost", endpoint.host);
ASSERT_EQ(9000u, endpoint.port);

client->ResetConnection();
endpoint = client->GetCurrentEndpoint().value();
endpoint = CurrentEndpoint(*client);
ASSERT_EQ("localhost", endpoint.host);
ASSERT_EQ(9000u, endpoint.port);

Expand Down
Loading