Skip to content

Commit e251d21

Browse files
authored
Merge pull request ClickHouse#131 from ClickHouse/windows-gh-actions
Add support for MSVC
2 parents b36c87f + be3175e commit e251d21

File tree

13 files changed

+177
-41
lines changed

13 files changed

+177
-41
lines changed

.github/workflows/windows_msvc.yml

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
name: Windows
2+
3+
on:
4+
push:
5+
branches: [ master ]
6+
pull_request:
7+
branches: [ master ]
8+
9+
env:
10+
BUILD_TYPE: Release
11+
GTEST_FILTER: --gtest_filter=-"*"
12+
CLICKHOUSE_USER: clickhouse_cpp_cicd
13+
CLICKHOUSE_PASSWORD: clickhouse_cpp_cicd
14+
#
15+
# CLICKHOUSE_HOST: localhost
16+
# CLICKHOUSE_PORT: 9000
17+
# CLICKHOUSE_USER: default
18+
# CLICKHOUSE_PASSWORD:
19+
# CLICKHOUSE_DB: default
20+
#
21+
# CLICKHOUSE_SECURE_HOST: github.demo.trial.altinity.cloud
22+
# CLICKHOUSE_SECURE_PORT: 9440
23+
# CLICKHOUSE_SECURE_USER: demo
24+
# CLICKHOUSE_SECURE_PASSWORD: demo
25+
# CLICKHOUSE_SECURE_DB: default
26+
#
27+
# CLICKHOUSE_SECURE2_HOST: gh-api.clickhouse.tech
28+
# CLICKHOUSE_SECURE2_PORT: 9440
29+
# CLICKHOUSE_SECURE2_USER: explorer
30+
# CLICKHOUSE_SECURE2_PASSWORD:
31+
# CLICKHOUSE_SECURE2_DB: default
32+
33+
jobs:
34+
build:
35+
runs-on: windows-latest
36+
37+
steps:
38+
- uses: actions/checkout@v2
39+
- uses: ilammy/msvc-dev-cmd@v1
40+
41+
- name: Configure CMake
42+
run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DBUILD_TESTS=ON
43+
44+
- name: Build
45+
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}
46+
47+
- name: Start tls offoader proxy
48+
shell: bash
49+
# that mimics non-secure clickhouse running on localhost
50+
# by tunneling queries to remote tls server
51+
# (needed because we can't start real clickhouse instance on windows)
52+
run: |
53+
choco install wget
54+
wget https://github.com/filimonov/go-tlsoffloader/releases/download/v0.1.2/go-tlsoffloader_0.1.2_Windows_x86_64.tar.gz
55+
tar -xvzf go-tlsoffloader_0.1.2_Windows_x86_64.tar.gz
56+
./go-tlsoffloader.exe -l localhost:9000 -b github.demo.trial.altinity.cloud:9440 &
57+
58+
- name: Test
59+
working-directory: ${{github.workspace}}/build/ut
60+
run: Release\clickhouse-cpp-ut.exe "${{env.GTEST_FILTER}}"

clickhouse/base/compressed.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ void CompressedOutput::Compress(const void * data, size_t len) {
142142
(const char*)data,
143143
(char*)compressed_buffer_.data() + HEADER_SIZE,
144144
len,
145-
compressed_buffer_.size() - HEADER_SIZE);
145+
static_cast<int>(compressed_buffer_.size() - HEADER_SIZE));
146146
if (compressed_size <= 0)
147147
throw std::runtime_error("Failed to compress chunk of " + std::to_string(len) + " bytes, "
148148
"LZ4 error: " + std::to_string(compressed_size));
@@ -164,7 +164,7 @@ void CompressedOutput::Compress(const void * data, size_t len) {
164164
}
165165

166166
void CompressedOutput::PreallocateCompressBuffer(size_t input_size) {
167-
const auto estimated_compressed_buffer_size = LZ4_compressBound(input_size);
167+
const auto estimated_compressed_buffer_size = LZ4_compressBound(static_cast<int>(input_size));
168168
if (estimated_compressed_buffer_size <= 0)
169169
throw std::runtime_error("Failed to estimate compressed buffer size, LZ4 error: " + std::to_string(estimated_compressed_buffer_size));
170170

clickhouse/base/platform.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313

1414
#if defined(_win32_) || defined(_win64_)
1515
# define _win_
16+
# define _WIN32_WINNT 0x0600 // The WSAPoll function is defined on Windows Vista and later.
17+
# define WIN32_LEAN_AND_MEAN 1 // don't include too much header automatically
1618
#endif
1719

1820
#if defined(_linux_) || defined (_darwin_)

clickhouse/base/socket.cpp

Lines changed: 55 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,33 @@
1414
# include <netinet/tcp.h>
1515
# include <signal.h>
1616
# include <unistd.h>
17-
# include <netinet/tcp.h>
1817
#endif
1918

2019
namespace clickhouse {
2120

21+
#if defined(_win_)
22+
char const* windowsErrorCategory::name() const noexcept {
23+
return "WindowsSocketError";
24+
}
25+
26+
std::string windowsErrorCategory::message(int c) const {
27+
char error[UINT8_MAX];
28+
auto len = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, nullptr, static_cast<DWORD>(c), 0, error, sizeof(error), nullptr);
29+
if (len == 0) {
30+
return "unknown";
31+
}
32+
while (len && (error[len - 1] == '\r' || error[len - 1] == '\n')) {
33+
--len;
34+
}
35+
return std::string(error, len);
36+
}
37+
38+
windowsErrorCategory const& windowsErrorCategory::category() {
39+
static windowsErrorCategory c;
40+
return c;
41+
}
42+
#endif
43+
2244
namespace {
2345

2446
class LocalNames : public std::unordered_set<std::string> {
@@ -37,6 +59,22 @@ class LocalNames : public std::unordered_set<std::string> {
3759
}
3860
};
3961

62+
inline int getSocketErrorCode() {
63+
#if defined(_win_)
64+
return WSAGetLastError();
65+
#else
66+
return errno;
67+
#endif
68+
}
69+
70+
const std::error_category& getErrorCategory() noexcept {
71+
#if defined(_win_)
72+
return windowsErrorCategory::category();
73+
#else
74+
return std::system_category();
75+
#endif
76+
}
77+
4078
void SetNonBlock(SOCKET fd, bool value) {
4179
#if defined(_unix_)
4280
int flags;
@@ -55,8 +93,7 @@ void SetNonBlock(SOCKET fd, bool value) {
5593
return ioctl(fd, FIOBIO, &flags);
5694
#endif
5795
if (ret == -1) {
58-
throw std::system_error(
59-
errno, std::system_category(), "fail to set nonblocking mode");
96+
throw std::system_error(getSocketErrorCode(), getErrorCategory(), "fail to set nonblocking mode");
6097
}
6198
#elif defined(_win_)
6299
unsigned long inbuf = value;
@@ -68,8 +105,7 @@ void SetNonBlock(SOCKET fd, bool value) {
68105
}
69106

70107
if (WSAIoctl(fd, FIONBIO, &inbuf, sizeof(inbuf), &outbuf, sizeof(outbuf), &written, 0, 0) == SOCKET_ERROR) {
71-
throw std::system_error(
72-
errno, std::system_category(), "fail to set nonblocking mode");
108+
throw std::system_error(getSocketErrorCode(), getErrorCategory(), "fail to set nonblocking mode");
73109
}
74110
#endif
75111
}
@@ -94,16 +130,21 @@ SOCKET SocketConnect(const NetworkAddress& addr) {
94130
SetNonBlock(s, true);
95131

96132
if (connect(s, res->ai_addr, (int)res->ai_addrlen) != 0) {
97-
int err = errno;
98-
if (err == EINPROGRESS || err == EAGAIN || err == EWOULDBLOCK) {
133+
int err = getSocketErrorCode();
134+
if (
135+
err == EINPROGRESS || err == EAGAIN || err == EWOULDBLOCK
136+
#if defined(_win_)
137+
|| err == WSAEWOULDBLOCK || err == WSAEINPROGRESS
138+
#endif
139+
) {
99140
pollfd fd;
100141
fd.fd = s;
101142
fd.events = POLLOUT;
102143
fd.revents = 0;
103144
ssize_t rval = Poll(&fd, 1, 5000);
104145

105146
if (rval == -1) {
106-
throw std::system_error(errno, std::system_category(), "fail to connect");
147+
throw std::system_error(getSocketErrorCode(), getErrorCategory(), "fail to connect");
107148
}
108149
if (rval > 0) {
109150
socklen_t len = sizeof(err);
@@ -122,11 +163,9 @@ SOCKET SocketConnect(const NetworkAddress& addr) {
122163
}
123164
}
124165
if (last_err > 0) {
125-
throw std::system_error(last_err, std::system_category(), "fail to connect");
166+
throw std::system_error(last_err, getErrorCategory(), "fail to connect");
126167
}
127-
throw std::system_error(
128-
errno, std::system_category(), "fail to connect"
129-
);
168+
throw std::system_error(getSocketErrorCode(), getErrorCategory(), "fail to connect");
130169
}
131170

132171
} // namespace
@@ -156,7 +195,7 @@ NetworkAddress::NetworkAddress(const std::string& host, const std::string& port)
156195
const int error = getaddrinfo(host.c_str(), port.c_str(), &hints, &info_);
157196

158197
if (error) {
159-
throw std::system_error(errno, std::system_category());
198+
throw std::system_error(getSocketErrorCode(), getErrorCategory());
160199
}
161200
}
162201

@@ -262,14 +301,10 @@ size_t SocketInput::DoRead(void* buf, size_t len) {
262301
}
263302

264303
if (ret == 0) {
265-
throw std::system_error(
266-
errno, std::system_category(), "closed"
267-
);
304+
throw std::system_error(getSocketErrorCode(), getErrorCategory(), "closed");
268305
}
269306

270-
throw std::system_error(
271-
errno, std::system_category(), "can't receive string data"
272-
);
307+
throw std::system_error(getSocketErrorCode(), getErrorCategory(), "can't receive string data");
273308
}
274309

275310
bool SocketInput::Skip(size_t /*bytes*/) {
@@ -292,9 +327,7 @@ size_t SocketOutput::DoWrite(const void* data, size_t len) {
292327
#endif
293328

294329
if (::send(s_, (const char*)data, (int)len, flags) != (int)len) {
295-
throw std::system_error(
296-
errno, std::system_category(), "fail to send " + std::to_string(len) + " bytes of data"
297-
);
330+
throw std::system_error(getSocketErrorCode(), getErrorCategory(), "fail to send " + std::to_string(len) + " bytes of data");
298331
}
299332

300333
return len;

clickhouse/base/socket.h

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
#pragma once
22

3+
#include "platform.h"
34
#include "input.h"
45
#include "output.h"
5-
#include "platform.h"
66

77
#include <cstddef>
88
#include <string>
@@ -24,7 +24,7 @@
2424
#endif
2525

2626
#include <memory>
27-
27+
#include <system_error>
2828

2929
struct addrinfo;
3030

@@ -47,6 +47,17 @@ class NetworkAddress {
4747
struct addrinfo* info_;
4848
};
4949

50+
#if defined(_win_)
51+
52+
class windowsErrorCategory : public std::error_category {
53+
public:
54+
char const* name() const noexcept override final;
55+
std::string message(int c) const override final;
56+
57+
static windowsErrorCategory const& category();
58+
};
59+
60+
#endif
5061

5162
class Socket {
5263
public:

clickhouse/client.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -328,9 +328,10 @@ void Client::Impl::ResetConnection() {
328328
socket = std::make_unique<Socket>(address);
329329

330330
if (options_.tcp_keepalive) {
331-
socket->SetTcpKeepAlive(options_.tcp_keepalive_idle.count(),
332-
options_.tcp_keepalive_intvl.count(),
333-
options_.tcp_keepalive_cnt);
331+
socket->SetTcpKeepAlive(
332+
static_cast<int>(options_.tcp_keepalive_idle.count()),
333+
static_cast<int>(options_.tcp_keepalive_intvl.count()),
334+
static_cast<int>(options_.tcp_keepalive_cnt));
334335
}
335336
if (options_.tcp_nodelay) {
336337
socket->SetTcpNoDelay(options_.tcp_nodelay);

clickhouse/columns/decimal.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ void ColumnDecimal::Append(const std::string& value) {
134134
bool sign = true;
135135
bool has_dot = false;
136136

137-
int zeros = 0;
137+
size_t zeros = 0;
138138

139139
while (c != end) {
140140
if (*c == '-') {

tests/simple/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ ADD_EXECUTABLE (simple-test
33
)
44

55
TARGET_LINK_LIBRARIES (simple-test
6-
clickhouse-cpp-lib
6+
clickhouse-cpp-lib-static
77
)
88

99
IF (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")

ut/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ ADD_EXECUTABLE (clickhouse-cpp-ut
2525
)
2626

2727
TARGET_LINK_LIBRARIES (clickhouse-cpp-ut
28-
clickhouse-cpp-lib
28+
clickhouse-cpp-lib-static
2929
gtest-lib
3030
)
3131
IF (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")

ut/columns_ut.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -457,8 +457,17 @@ TEST(ColumnsCase, Int128) {
457457
absl::MakeInt128(0x8000000000000000ll, 0),
458458
Int128(0)
459459
});
460+
460461
EXPECT_EQ(-1, col->At(0));
461-
EXPECT_EQ(0xffffffffffffffffll, col->At(1));
462+
463+
EXPECT_EQ(absl::MakeInt128(0, 0xffffffffffffffffll), col->At(1));
464+
EXPECT_EQ(0ll, absl::Int128High64(col->At(1)));
465+
EXPECT_EQ(0xffffffffffffffffull, absl::Int128Low64(col->At(1)));
466+
467+
EXPECT_EQ(absl::MakeInt128(0xffffffffffffffffll, 0), col->At(2));
468+
EXPECT_EQ(static_cast<int64_t>(0xffffffffffffffffll), absl::Int128High64(col->At(2)));
469+
EXPECT_EQ(0ull, absl::Int128Low64(col->At(2)));
470+
462471
EXPECT_EQ(0, col->At(4));
463472
}
464473

ut/readonly_client_test.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ void ReadonlyClientTest::TearDown() {
1818
client_.reset();
1919
}
2020

21+
// Sometimes gtest fails to detect that this test is instantiated elsewhere, suppress the error explicitly.
22+
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ReadonlyClientTest);
2123
TEST_P(ReadonlyClientTest, Select) {
2224

2325
const auto & queries = std::get<1>(GetParam());

0 commit comments

Comments
 (0)