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
11 changes: 7 additions & 4 deletions clickhouse/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,7 @@ SET ( clickhouse-cpp-lib-src
)

ADD_LIBRARY (clickhouse-cpp-lib SHARED ${clickhouse-cpp-lib-src})

SET_TARGET_PROPERTIES(clickhouse-cpp-lib
PROPERTIES LINKER_LANGUAGE CXX)

SET_TARGET_PROPERTIES(clickhouse-cpp-lib PROPERTIES LINKER_LANGUAGE CXX)
TARGET_LINK_LIBRARIES (clickhouse-cpp-lib
cityhash-lib
lz4-lib
Expand All @@ -43,6 +40,12 @@ TARGET_LINK_LIBRARIES (clickhouse-cpp-lib-static
lz4-lib
)

IF (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} --rtlib=compiler-rt")
TARGET_LINK_LIBRARIES (clickhouse-cpp-lib gcc_s)
TARGET_LINK_LIBRARIES (clickhouse-cpp-lib-static gcc_s)
ENDIF ()

INSTALL(TARGETS clickhouse-cpp-lib clickhouse-cpp-lib-static
ARCHIVE DESTINATION lib
LIBRARY DESTINATION lib
Expand Down
39 changes: 32 additions & 7 deletions clickhouse/columns/decimal.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#include "decimal.h"

#include <iostream>

namespace clickhouse {

ColumnDecimal::ColumnDecimal(size_t precision, size_t scale)
Expand Down Expand Up @@ -32,26 +34,49 @@ void ColumnDecimal::Append(const Int128& value) {
void ColumnDecimal::Append(const std::string& value) {
Int128 int_value = 0;
auto c = value.begin();
auto end = value.end();
bool sign = true;
bool has_dot = false;

int zeros = 0;

while (c != value.end()) {
while (c != end) {
if (*c == '-') {
sign = false;
if (c != value.begin()) {
break;
}
} else if (*c == '.') {
// TODO: compare distance with `scale`
} else if (*c == '.' && !has_dot) {
size_t distance = std::distance(c, end) - 1;
auto scale = type_->As<DecimalType>()->GetScale();

if (distance <= scale) {
zeros = scale - distance;
} else {
std::advance(end, scale - distance);
}

has_dot = true;
} else if (*c >= '0' && *c <= '9') {
int_value = int_value * 10 + (*c - '0');
if (__builtin_mul_overflow(int_value, 10, &int_value) ||
__builtin_add_overflow(int_value, *c - '0', &int_value)) {
throw std::runtime_error("value is too big for 128-bit integer");
}
} else {
// TODO: throw exception on unexpected symbol
throw std::runtime_error(std::string("unexpected symbol '") + (*c) + "' in decimal value");
}
++c;
}

if (c != value.end()) {
// TODO: throw exception about symbols after 'minus'
if (c != end) {
throw std::runtime_error("unexpected symbol '-' in decimal value");
}

while (zeros) {
if (__builtin_mul_overflow(int_value, 10, &int_value)) {
throw std::runtime_error("value is too big for 128-bit integer");
}
--zeros;
}

Append(sign ? int_value : -int_value);
Expand Down
45 changes: 42 additions & 3 deletions ut/client_ut.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,31 @@ TEST_P(ClientCase, Decimal) {
auto d5 = std::make_shared<ColumnDecimal>(18, 9);
auto d6 = std::make_shared<ColumnDecimal>(38, 19);

EXPECT_THROW(
d1->Append("1234567890123456789012345678901234567890"),
std::runtime_error
);
EXPECT_THROW(
d1->Append("123456789012345678901234567890123456.7890"),
std::runtime_error
);
EXPECT_THROW(
d1->Append("-1234567890123456789012345678901234567890"),
std::runtime_error
);
EXPECT_THROW(
d1->Append("12345678901234567890123456789012345678a"),
std::runtime_error
);
EXPECT_THROW(
d1->Append("12345678901234567890123456789012345678-"),
std::runtime_error
);
EXPECT_THROW(
d1->Append("1234.12.1234"),
std::runtime_error
);

id->Append(1);
d1->Append(123456789);
d2->Append(123456789012345678);
Expand All @@ -401,7 +426,6 @@ TEST_P(ClientCase, Decimal) {
d6->Append(-999999999999999999);

// Check strings with decimal point
// TODO: check that exception is thrown if point doesn't match the `scale`
id->Append(4);
d1->Append("12345.6789");
d2->Append("123456789.012345678");
Expand All @@ -419,6 +443,14 @@ TEST_P(ClientCase, Decimal) {
d5->Append("-123456789012345678");
d6->Append("-12345678901234567890123456789012345678");

id->Append(6);
d1->Append("12345.678");
d2->Append("123456789.0123456789");
d3->Append("1234567890123456789.0123456789012345678");
d4->Append("12345.6789");
d5->Append("123456789.012345678");
d6->Append("1234567890123456789.0123456789012345678");

b.AppendColumn("id", id);
b.AppendColumn("d1", d1);
b.AppendColumn("d2", d2);
Expand All @@ -435,7 +467,7 @@ TEST_P(ClientCase, Decimal) {
return;
}

ASSERT_EQ(5u, b.GetRowCount());
ASSERT_EQ(6u, b.GetRowCount());

auto int128_to_string = [](Int128 value) {
std::string result;
Expand Down Expand Up @@ -504,6 +536,14 @@ TEST_P(ClientCase, Decimal) {
EXPECT_EQ("-123456789", int128_to_string(decimal(4, 4)));
EXPECT_EQ("-123456789012345678", int128_to_string(decimal(5, 4)));
EXPECT_EQ("-12345678901234567890123456789012345678", int128_to_string(decimal(6, 4)));

EXPECT_EQ(6u, b[0]->As<ColumnUInt64>()->At(5));
EXPECT_EQ("123456780", int128_to_string(decimal(1, 5)));
EXPECT_EQ("123456789012345678", int128_to_string(decimal(2, 5)));
EXPECT_EQ("12345678901234567890123456789012345678", int128_to_string(decimal(3, 5)));
EXPECT_EQ("123456789", int128_to_string(decimal(4, 5)));
EXPECT_EQ("123456789012345678", int128_to_string(decimal(5, 5)));
EXPECT_EQ("12345678901234567890123456789012345678", int128_to_string(decimal(6, 5)));
});
}

Expand All @@ -518,4 +558,3 @@ INSTANTIATE_TEST_CASE_P(
.SetPingBeforeQuery(false)
.SetCompressionMethod(CompressionMethod::LZ4)
));