Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

support Timeplusd #2

Merged
merged 22 commits into from
Jul 26, 2024
Merged
Show file tree
Hide file tree
Changes from 21 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
32 changes: 23 additions & 9 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ INCLUDE (openssl)
INCLUDE (version)

OPTION (BUILD_BENCHMARK "Build benchmark" OFF)
OPTION (BUILD_TESTS "Build tests" OFF)
OPTION (BUILD_TESTS "Build tests" ON)
OPTION (BUILD_EXAMPLES "Build examples" ON)
OPTION (BUILD_SHARED_LIBS "Build shared libs" OFF)
OPTION (WITH_OPENSSL "Use OpenSSL for TLS connections" OFF)
OPTION (WITH_SYSTEM_ABSEIL "Use system ABSEIL" OFF)
Expand All @@ -17,17 +18,18 @@ OPTION (WITH_SYSTEM_CITYHASH "Use system cityhash" 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 (BUILD_GTEST "Build Google Test" ON)

PROJECT (CLICKHOUSE-CLIENT
VERSION "${CLICKHOUSE_CPP_VERSION}"
DESCRIPTION "ClickHouse C++ client library"
PROJECT (TIMEPLUS-CLIENT
VERSION "${TIMEPLUS_CPP_VERSION}"
DESCRIPTION "Timeplus C++ client library"
)

USE_CXX17 ()
USE_OPENSSL ()

IF (CHECK_VERSION)
clickhouse_cpp_check_library_version(FATAL_ERROR)
timeplus_cpp_check_library_version(FATAL_ERROR)
ENDIF ()

IF (NOT CMAKE_BUILD_TYPE)
Expand Down Expand Up @@ -102,22 +104,34 @@ ELSE ()
ENDIF ()

SUBDIRS (
clickhouse
timeplus
)

IF (BUILD_BENCHMARK)
SUBDIRS (bench)
ENDIF (BUILD_BENCHMARK)

IF (BUILD_TESTS)
IF (BUILD_GTEST)
INCLUDE_DIRECTORIES (contrib/gtest/include contrib/gtest)
SUBDIRS (
contrib/gtest
tests/simple
ut
)
ENDIF (BUILD_GTEST)

IF (BUILD_TESTS)
INCLUDE_DIRECTORIES (contrib/gtest/include contrib/gtest)
SUBDIRS (
tests/simple
)
ENDIF (BUILD_TESTS)

IF (BUILD_EXAMPLES)
SUBDIRS (
examples
)
ENDIF (BUILD_EXAMPLES)

if(DEBUG_DEPENDENCIES)
function(print_target_properties target)
MESSAGE("${target} properties:")
Expand All @@ -131,7 +145,7 @@ if(DEBUG_DEPENDENCIES)
# so have to create a target to fetch that info at generate time.
string(REPLACE ":" "_" target_plain_name ${target})
add_custom_target(${target_plain_name}_print_debug_info COMMAND ${CMAKE_COMMAND} -E echo "${target} : $<TARGET_FILE:${target}>")
add_dependencies(clickhouse-cpp-lib ${target_plain_name}_print_debug_info)
add_dependencies(timeplus-cpp-lib ${target_plain_name}_print_debug_info)
endfunction()

function(print_target_debug_info target)
Expand Down
153 changes: 83 additions & 70 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,28 +1,25 @@
Timeplus C++ client [![Linux](https://github.com/timeplus-io/timeplus-cpp/actions/workflows/linux.yml/badge.svg)](https://github.com/timeplus-io/timeplus-cpp/actions/workflows/linux.yml) [![macOS](https://github.com/timeplus-io/timeplus-cpp/actions/workflows/macos.yml/badge.svg)](https://github.com/timeplus-io/timeplus-cpp/actions/workflows/macos.yml) [![Windows MSVC](https://github.com/timeplus-io/timeplus-cpp/actions/workflows/windows_msvc.yml/badge.svg)](https://github.com/timeplus-io/timeplus-cpp/actions/workflows/windows_msvc.yml) [![Windows mingw](https://github.com/timeplus-io/timeplus-cpp/actions/workflows/windows_mingw.yml/badge.svg)](https://github.com/timeplus-io/timeplus-cpp/actions/workflows/windows_mingw.yml)
=====
Timeplus C++ client

C++ client for [Timeplus](https://timeplus.com/).
C++ client for [Timeplus](https://www.timeplus.com/).

## Supported data types

* Array(T)
* Date
* DateTime, DateTime64
* DateTime([timezone]), DateTime64(N, [timezone])
* Decimal32, Decimal64, Decimal128
* Enum8, Enum16
* FixedString(N)
* Float32, Float64
* IPv4, IPv6
* Nullable(T)
* String
* LowCardinality(String) or LowCardinality(FixedString(N))
* Tuple
* UInt8, UInt16, UInt32, UInt64, Int8, Int16, Int32, Int64
* Int128
* UUID
* Map
* Point, Ring, Polygon, MultiPolygon
* array(T)
* date
* datetime, datetime64
* datetime([timezone]), datetime64(N, [timezone])
* decimal32, decimal64, decimal128, decimal256
* enum8, enum16
* fixed_string(N)
* float32, float64
* ipv4, ipv6
* nullable(T)
* string
* low_cardinality(string) or low_cardinality(fixed_string(N))
* tuple
* uint8, uint16, uint32, uint64, uint128, uint256, int8, int16, int32, int64, int128, int256
* uuid
* map

## Dependencies
In the most basic case one needs only:
Expand All @@ -36,44 +33,53 @@ Optional dependencies:
- libabsl
- libzstd


## Building

```sh
$ mkdir build .
$ cd build
$ cmake .. [-DBUILD_TESTS=ON]
$ cmake -D CMAKE_BUILD_TYPE=Release ..
$ make
```

Plese refer to the workflows for the reference on dependencies/build options
- https://github.com/timeplus-io/timeplus-cpp/blob/master/.github/workflows/linux.yml
- https://github.com/timeplus-io/timeplus-cpp/blob/master/.github/workflows/windows_msvc.yml
- https://github.com/timeplus-io/timeplus-cpp/blob/master/.github/workflows/windows_mingw.yml
- https://github.com/timeplus-io/timeplus-cpp/blob/master/.github/workflows/macos.yml


## Example application build with timeplus-cpp

There are various ways to integrate clickhouse-cpp with the build system of an application. Below example uses the simple approach based on
submodules presented in https://www.youtube.com/watch?v=ED-WUk440qc .
### sample code


- `mkdir timeplus-cpp && cd timeplus-cpp && git init`
- `git submodule add https://github.com/timeplus-io/timeplus-cpp.git contribs/timeplus-cpp`
- `touch app.cpp`, then copy the following C++ code into that file
```
timeplus-cpp/examples/main.cpp
```

```cpp
#include <iostream>
#include <timeplus/client.h>

using namespace timeplus;

int main()
{
void createAndSelect(Client& client) {
/// Initialize client connection.
Client client(ClientOptions().SetHost("localhost"));
Client client(ClientOptions().SetHost("localhost").SetPort(8463));// your server's port

/// Create a table.
client.Execute("CREATE TABLE IF NOT EXISTS default.numbers (id UInt64, name String) ENGINE = Memory");
client.Execute("CREATE STREAM IF NOT EXISTS default.numbers (id uint64, name string)");

/// Select values inserted in the previous step.
client.Select("SELECT id, name FROM default.numbers", [] (const Block& block)
{
for (size_t i = 0; i < block.GetRowCount(); ++i) {
std::cout << block[0]->As<ColumnUInt64>()->At(i) << " "
<< block[1]->As<ColumnString>()->At(i) << "\n";
}
}
);

}

void insertStream(Client& client) {


/// Insert some values.
{
Expand All @@ -92,50 +98,57 @@ int main()

client.Insert("default.numbers", block);
}
}

/// Select values inserted in the previous step.
client.Select("SELECT id, name FROM default.numbers", [] (const Block& block)
{
for (size_t i = 0; i < block.GetRowCount(); ++i) {
std::cout << block[0]->As<ColumnUInt64>()->At(i) << " "
<< block[1]->As<ColumnString>()->At(i) << "\n";
}
}
);

/// Delete table.
client.Execute("DROP TABLE default.numbers");

return 0;
void dropStream(Client& client) {
/// Delete stream.
client.Execute("DROP STREAM IF EXISTS default.numbers");
}
```

- `touch CMakeLists.txt`, then copy the following CMake code into that file
void (*functionPointers[])(Client&) = {createAndSelect, insertStream};

```cmake
cmake_minimum_required(VERSION 3.12)
project(application-example)
int main(int argc, char* argv[]) {
if (argc != 2) {
std::cerr << "Usage: " << argv[0] << " <function_number>" << std::endl;
return 1;
}

set(CMAKE_CXX_STANDARD 17)
int functionNumber = std::stoi(argv[1]);

add_subdirectory(contribs/timeplus-cpp)
if (functionNumber < 1 || functionNumber > 3) {
std::cerr << "Invalid function number. Please enter: "<<"\n"
<< "1 (create stream)" <<"\n"
<< "2 (insert into stream)" <<"\n"
<< "3 (delete stream)" <<std::endl;
return 1;
}

/// Initialize client connection.
Client client(ClientOptions().SetHost("localhost").SetPort(8463));

add_executable(${PROJECT_NAME} "app.cpp")

target_include_directories(${PROJECT_NAME} PRIVATE contribs/timeplus-cpp/ contribs/timeplus-cpp/contrib/absl)
functionPointers[functionNumber - 1](client);

target_link_libraries(${PROJECT_NAME} PRIVATE timeplus-cpp-lib)
return 0;
}
```

- run `rm -rf build && cmake -B build -S . && cmake --build build -j32` to remove remainders of the previous builds, run CMake and build the
application. The generated binary is located in location `build/application-example`.

## Thread-safety
⚠ Please note that `Client` instance is NOT thread-safe. I.e. you must create a separate `Client` for each thread or utilize some synchronization techniques. ⚠

## Retries
If you wish to implement some retry logic atop of `timeplus::Client` there are few simple rules to make you life easier:
- If previous attempt threw an exception, then make sure to call `timeplus::Client::ResetConnection()` before the next try.
- For `timeplus::Client::Insert()` you can reuse a block from previous try, no need to rebuild it from scratch.
```sh
# terminal 1
# current path should be /timeplus-cpp
# create stream and start select
$ ./build/example/timeplus-client 1

# new terminal 2
# insert into stream
$ ./build/example/timeplus-client 2

# back to terminal 1, the insert values will be printed

# terminal 2
# delete stream
$ ./build/example/timeplus-client 3
```

See https://github.com/ClickHouse/clickhouse-cpp/issues/184 for details.
2 changes: 1 addition & 1 deletion bench/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@ ADD_EXECUTABLE (bench
)

TARGET_LINK_LIBRARIES (bench
clickhouse-cpp-lib
timeplus-cpp-lib
benchmark
)
14 changes: 7 additions & 7 deletions bench/bench.cpp
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
#include <benchmark/benchmark.h>

#include <clickhouse/client.h>
#include <timeplus/client.h>
#include <ut/utils.h>

namespace clickhouse {
namespace timeplus {

Client g_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"))
.SetHost( getEnvOrDefault("TIMEPLUS_HOST", "localhost"))
.SetPort( std::stoi(getEnvOrDefault("TIMEPLUS_PORT", "8463")))
.SetUser( getEnvOrDefault("TIMEPLUS_USER", "default"))
.SetPassword( getEnvOrDefault("TIMEPLUS_PASSWORD", ""))
.SetDefaultDatabase(getEnvOrDefault("TIMEPLUS_DB", "default"))
.SetPingBeforeQuery(false));

static void SelectNumber(benchmark::State& state) {
Expand Down
12 changes: 0 additions & 12 deletions clickhouse/base/uuid.h

This file was deleted.

14 changes: 0 additions & 14 deletions clickhouse/version.h

This file was deleted.

Loading