Skip to content

Commit aa15fc0

Browse files
committed
Fixed issues found during PR review
Fragile implementation of ItemView::ValidateData And several other minor issues.
1 parent 615721a commit aa15fc0

File tree

4 files changed

+89
-66
lines changed

4 files changed

+89
-66
lines changed

clickhouse/columns/date.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ void ColumnDateTime64::Append(const Int64& value) {
135135

136136
Int64 ColumnDateTime64::At(size_t n) const {
137137
// make sure to use Absl's Int128 conversion
138-
return static_cast<long long>(data_->At(n));
138+
return static_cast<Int64>(data_->At(n));
139139
}
140140

141141
void ColumnDateTime64::Append(ColumnRef column) {

clickhouse/columns/decimal.cpp

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ namespace
55
using namespace clickhouse;
66

77
#ifdef ABSL_HAVE_INTRINSIC_INT128
8-
inline bool addOverflow(const Int128 & l, const Int128 & r, Int128 * result)
8+
template <typename T>
9+
inline bool addOverflow(const Int128 & l, const T & r, Int128 * result)
910
{
1011
__int128 res;
1112
const auto ret_value = __builtin_add_overflow(static_cast<__int128>(l), static_cast<__int128>(r), &res);
@@ -14,7 +15,8 @@ inline bool addOverflow(const Int128 & l, const Int128 & r, Int128 * result)
1415
return ret_value;
1516
}
1617

17-
inline bool mulOverflow(const Int128 & l, const Int128 & r, Int128 * result)
18+
template <typename T>
19+
inline bool mulOverflow(const Int128 & l, const T & r, Int128 * result)
1820
{
1921
__int128 res;
2022
const auto ret_value = __builtin_mul_overflow(static_cast<__int128>(l), static_cast<__int128>(r), &res);
@@ -24,7 +26,13 @@ inline bool mulOverflow(const Int128 & l, const Int128 & r, Int128 * result)
2426
}
2527

2628
#else
27-
inline bool getSign(const Int128 & v)
29+
template <typename T>
30+
inline bool getSignBit(const T & v)
31+
{
32+
return std::signbit(v);
33+
}
34+
35+
inline bool getSignBit(const Int128 & v)
2836
{
2937
// static constexpr Int128 zero {};
3038
// return v < zero;
@@ -36,12 +44,12 @@ inline bool getSign(const Int128 & v)
3644
inline bool addOverflow(const Int128 & l, const Int128 & r, Int128 * result)
3745
{
3846
// *result = l + r;
39-
// const auto result_sign = getSign(*result);
47+
// const auto result_sign = getSignBit(*result);
4048
// return l_sign == r_sign && l_sign != result_sign;
4149

4250
// Based on code from:
4351
// https://wiki.sei.cmu.edu/confluence/display/c/INT32-C.+Ensure+that+operations+on+signed+integers+do+not+result+in+overflow#INT32C.Ensurethatoperationsonsignedintegersdonotresultinoverflow-CompliantSolution
44-
const auto r_positive = !getSign(r);
52+
const auto r_positive = !getSignBit(r);
4553

4654
if ((r_positive && (l > (std::numeric_limits<Int128>::max() - r))) ||
4755
(!r_positive && (l < (std::numeric_limits<Int128>::min() - r)))) {
@@ -52,30 +60,31 @@ inline bool addOverflow(const Int128 & l, const Int128 & r, Int128 * result)
5260
return false;
5361
}
5462

55-
inline bool mulOverflow(const Int128 & l, const Int128 & r, Int128 * result)
63+
template <typename T>
64+
inline bool mulOverflow(const Int128 & l, const T & r, Int128 * result)
5665
{
5766
// Based on code from:
5867
// https://wiki.sei.cmu.edu/confluence/display/c/INT32-C.+Ensure+that+operations+on+signed+integers+do+not+result+in+overflow#INT32C.Ensurethatoperationsonsignedintegersdonotresultinoverflow-CompliantSolution.3
59-
const auto l_positive = !getSign(l);
60-
const auto r_positive = !getSign(r);
68+
const auto l_positive = !getSignBit(l);
69+
const auto r_positive = !getSignBit(r);
6170

6271
if (l_positive) {
6372
if (r_positive) {
64-
if (l > (std::numeric_limits<Int128>::max() / r)) {
73+
if (r != 0 && l > (std::numeric_limits<Int128>::max() / r)) {
6574
return true;
6675
}
6776
} else {
68-
if (r < (std::numeric_limits<Int128>::min() / l)) {
77+
if (l != 0 && r < (std::numeric_limits<Int128>::min() / l)) {
6978
return true;
7079
}
7180
}
7281
} else {
7382
if (r_positive) {
74-
if (l < (std::numeric_limits<Int128>::min() / r)) {
83+
if (r != 0 && l < (std::numeric_limits<Int128>::min() / r)) {
7584
return true;
7685
}
7786
} else {
78-
if ( (l != 0) && (r < (std::numeric_limits<Int128>::max() / l))) {
87+
if (l != 0 && (r < (std::numeric_limits<Int128>::max() / l))) {
7988
return true;
8089
}
8190
}
@@ -145,8 +154,8 @@ void ColumnDecimal::Append(const std::string& value) {
145154

146155
has_dot = true;
147156
} else if (*c >= '0' && *c <= '9') {
148-
if (mulOverflow(int_value, Int128(10), &int_value) ||
149-
addOverflow(int_value, Int128(*c - '0'), &int_value)) {
157+
if (mulOverflow(int_value, 10, &int_value) ||
158+
addOverflow(int_value, *c - '0', &int_value)) {
150159
throw std::runtime_error("value is too big for 128-bit integer");
151160
}
152161
} else {
@@ -160,7 +169,7 @@ void ColumnDecimal::Append(const std::string& value) {
160169
}
161170

162171
while (zeros) {
163-
if (mulOverflow(int_value, Int128(10), &int_value)) {
172+
if (mulOverflow(int_value, 10, &int_value)) {
164173
throw std::runtime_error("value is too big for 128-bit integer");
165174
}
166175
--zeros;

clickhouse/columns/itemview.cpp

Lines changed: 62 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -3,52 +3,69 @@
33
namespace clickhouse {
44

55
void ItemView::ValidateData(Type::Code type, DataType data) {
6-
static const int ANY = -1; // value can be of any size
7-
static const int ERR = -2; // value is not allowed inside ItemView
8-
static const int value_size_by_type[] = {
9-
0, /*Void*/
10-
1, /*Int8*/
11-
2, /*Int16*/
12-
4, /*Int32*/
13-
8, /*Int64*/
14-
1, /*UInt8*/
15-
2, /*UInt16*/
16-
4, /*UInt32*/
17-
8, /*UInt64*/
18-
4, /*Float32*/
19-
8, /*Float64*/
20-
ANY, /*String*/
21-
ANY, /*FixedString*/
22-
4, /*DateTime*/
23-
2, /*Date*/
24-
ERR, /*Array*/
25-
ERR, /*Nullable*/
26-
ERR, /*Tuple*/
27-
1, /*Enum8*/
28-
2, /*Enum16*/
29-
16, /*UUID*/
30-
4, /*IPv4*/
31-
8, /*IPv6*/
32-
16, /*Int128*/
33-
16, /*Decimal*/
34-
4, /*Decimal32*/
35-
8, /*Decimal64*/
36-
16, /*Decimal128*/
37-
ERR, /*LowCardinality*/
38-
8, /*DateTime64*/
39-
};
40-
41-
if (type >= sizeof(value_size_by_type)/sizeof(value_size_by_type[0]) || type < 0) {
42-
throw std::runtime_error("Unknon type code:" + std::to_string(static_cast<int>(type)));
43-
} else {
44-
const auto expected_size = value_size_by_type[type];
45-
if (expected_size == ERR) {
6+
int expected_size = 0;
7+
switch (type) {
8+
case Type::Code::Void:
9+
expected_size = 0;
10+
break;
11+
12+
case Type::Code::Int8:
13+
case Type::Code::UInt8:
14+
case Type::Code::Enum8:
15+
expected_size = 1;
16+
break;
17+
18+
case Type::Code::Int16:
19+
case Type::Code::UInt16:
20+
case Type::Code::Date:
21+
case Type::Code::Enum16:
22+
expected_size = 2;
23+
break;
24+
25+
case Type::Code::Int32:
26+
case Type::Code::UInt32:
27+
case Type::Code::Float32:
28+
case Type::Code::DateTime:
29+
case Type::Code::IPv4:
30+
case Type::Code::Decimal32:
31+
expected_size = 4;
32+
break;
33+
34+
case Type::Code::Int64:
35+
case Type::Code::UInt64:
36+
case Type::Code::Float64:
37+
case Type::Code::DateTime64:
38+
case Type::Code::IPv6:
39+
case Type::Code::Decimal64:
40+
expected_size = 8;
41+
break;
42+
43+
case Type::Code::String:
44+
case Type::Code::FixedString:
45+
// value can be of any size
46+
return;
47+
48+
case Type::Code::Array:
49+
case Type::Code::Nullable:
50+
case Type::Code::Tuple:
51+
case Type::Code::LowCardinality:
4652
throw std::runtime_error("Unsupported type in ItemView: " + std::to_string(static_cast<int>(type)));
47-
} else if (expected_size != ANY && expected_size != static_cast<int>(data.size())) {
48-
throw std::runtime_error("Value size mismatch for type "
49-
+ std::to_string(static_cast<int>(type)) + " expected: "
50-
+ std::to_string(expected_size) + ", got: " + std::to_string(data.size()));
51-
}
53+
54+
case Type::Code::UUID:
55+
case Type::Code::Int128:
56+
case Type::Code::Decimal:
57+
case Type::Code::Decimal128:
58+
expected_size = 16;
59+
break;
60+
61+
default:
62+
throw std::runtime_error("Unknon type code:" + std::to_string(static_cast<int>(type)));
63+
}
64+
65+
if (expected_size != static_cast<int>(data.size())) {
66+
throw std::runtime_error("Value size mismatch for type "
67+
+ std::to_string(static_cast<int>(type)) + " expected: "
68+
+ std::to_string(expected_size) + ", got: " + std::to_string(data.size()));
5269
}
5370
}
5471

clickhouse/columns/itemview.h

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,10 @@ struct ItemView {
2626
inline auto ConvertToStorageValue(const T& t) {
2727
if constexpr (std::is_same_v<std::string_view, T> || std::is_same_v<std::string, T>) {
2828
return std::string_view{t};
29-
} else if constexpr (std::is_fundamental_v<T>) {
30-
return std::string_view{reinterpret_cast<const char*>(&t), sizeof(T)};
31-
}
32-
else if constexpr (std::is_same_v<Int128, std::decay_t<T>>) {
29+
} else if constexpr (std::is_fundamental_v<T> || std::is_same_v<Int128, std::decay_t<T>>) {
3330
return std::string_view{reinterpret_cast<const char*>(&t), sizeof(T)};
3431
} else {
35-
// will caue error at compile-time
32+
// will cause a compile-time error
3633
return;
3734
}
3835
}

0 commit comments

Comments
 (0)