Skip to content

Commit 733417d

Browse files
artpaulabyss7
authored andcommitted
Decimal type support (ClickHouse#95)
* initial support of decimal types * parse decimal types & ut * fix append
1 parent e04d7ae commit 733417d

14 files changed

+166
-78
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,11 @@ C++ client for [Yandex ClickHouse](https://clickhouse.yandex/)
1212
* Enum8, Enum16
1313
* FixedString(N)
1414
* Float32, Float64
15+
* IPv4, IPv6
1516
* Nullable(T)
1617
* String
1718
* Tuple
1819
* UInt8, UInt16, UInt32, UInt64, Int8, Int16, Int32, Int64
19-
* IPv4, IPv6
2020

2121
## Building
2222

clickhouse/columns/array.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ ColumnRef ColumnArray::Slice(size_t begin, size_t size) {
3838
{
3939
result->Append(std::make_shared<ColumnArray>(GetAsColumn(begin + i)));
4040
}
41-
41+
4242
return result;
4343
}
4444

clickhouse/columns/array.h

+3-3
Original file line numberDiff line numberDiff line change
@@ -28,16 +28,16 @@ class ColumnArray : public Column {
2828

2929
/// Saves column data to output stream.
3030
void Save(CodedOutputStream* output) override;
31-
31+
3232
/// Clear column data .
3333
void Clear() override;
34-
34+
3535
/// Returns count of rows in the column.
3636
size_t Size() const override;
3737

3838
/// Makes slice of the current column.
3939
ColumnRef Slice(size_t, size_t) override;
40-
40+
4141
void OffsetsIncrease(size_t);
4242

4343
private:

clickhouse/columns/decimal.cpp

+35-11
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,24 @@
11
#include "decimal.h"
22

3-
#include "numeric.h"
4-
53
namespace clickhouse {
64

7-
ColumnDecimal::ColumnDecimal(size_t precision, size_t scale) : Column(Type::CreateDecimal(precision, scale)) {
5+
ColumnDecimal::ColumnDecimal(size_t precision, size_t scale)
6+
: Column(Type::CreateDecimal(precision, scale))
7+
{
88
if (precision <= 9) {
9-
data_ = ColumnRef(new ColumnInt32());
9+
data_ = std::make_shared<ColumnInt32>();
1010
} else if (precision <= 18) {
11-
data_ = ColumnRef(new ColumnInt64());
11+
data_ = std::make_shared<ColumnInt64>();
1212
} else {
13-
data_ = ColumnRef(new ColumnInt128());
13+
data_ = std::make_shared<ColumnInt128>();
1414
}
1515
}
1616

17+
ColumnDecimal::ColumnDecimal(TypeRef type)
18+
: Column(type)
19+
{
20+
}
21+
1722
void ColumnDecimal::Append(const Int128& value) {
1823
if (data_->Type()->GetCode() == Type::Int32) {
1924
data_->As<ColumnInt32>()->Append(static_cast<ColumnInt32::DataType>(value));
@@ -24,7 +29,7 @@ void ColumnDecimal::Append(const Int128& value) {
2429
}
2530
}
2631

27-
void ColumnDecimal::Append(const std::string &value) {
32+
void ColumnDecimal::Append(const std::string& value) {
2833
Int128 int_value = 0;
2934
auto c = value.begin();
3035
bool sign = true;
@@ -62,13 +67,32 @@ Int128 ColumnDecimal::At(size_t i) const {
6267
}
6368
}
6469

70+
void ColumnDecimal::Append(ColumnRef column) {
71+
if (auto col = column->As<ColumnDecimal>()) {
72+
data_->Append(col->data_);
73+
}
74+
}
75+
76+
bool ColumnDecimal::Load(CodedInputStream* input, size_t rows) {
77+
return data_->Load(input, rows);
78+
}
79+
80+
void ColumnDecimal::Save(CodedOutputStream* output) {
81+
data_->Save(output);
82+
}
83+
84+
void ColumnDecimal::Clear() {
85+
data_->Clear();
86+
}
87+
88+
size_t ColumnDecimal::Size() const {
89+
return data_->Size();
90+
}
91+
6592
ColumnRef ColumnDecimal::Slice(size_t begin, size_t len) {
66-
std::shared_ptr<ColumnDecimal> slice(new ColumnDecimal(Type()));
93+
std::shared_ptr<ColumnDecimal> slice(new ColumnDecimal(type_));
6794
slice->data_ = data_->Slice(begin, len);
6895
return slice;
6996
}
7097

71-
ColumnDecimal::ColumnDecimal(TypeRef type) : Column(type) {
7298
}
73-
74-
} // namespace clickhouse

clickhouse/columns/decimal.h

+7-9
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,13 @@
11
#pragma once
22

33
#include "column.h"
4+
#include "numeric.h"
45

56
namespace clickhouse {
67

7-
using Int128 = __int128;
8-
98
/**
109
* Represents a column of decimal type.
1110
*/
12-
1311
class ColumnDecimal : public Column {
1412
public:
1513
ColumnDecimal(size_t precision, size_t scale);
@@ -20,11 +18,11 @@ class ColumnDecimal : public Column {
2018
Int128 At(size_t i) const;
2119

2220
public:
23-
void Append(ColumnRef column) override { data_->Append(column); }
24-
bool Load(CodedInputStream* input, size_t rows) override { return data_->Load(input, rows); }
25-
void Save(CodedOutputStream* output) override { data_->Save(output); }
26-
void Clear() override { data_->Clear(); }
27-
size_t Size() const override { return data_->Size(); }
21+
void Append(ColumnRef column) override;
22+
bool Load(CodedInputStream* input, size_t rows) override;
23+
void Save(CodedOutputStream* output) override;
24+
void Clear() override;
25+
size_t Size() const override;
2826
ColumnRef Slice(size_t begin, size_t len) override;
2927

3028
private:
@@ -37,4 +35,4 @@ class ColumnDecimal : public Column {
3735
explicit ColumnDecimal(TypeRef type); // for `Slice(…)`
3836
};
3937

40-
} // namespace clickhouse
38+
}

clickhouse/columns/factory.cpp

+12-15
Original file line numberDiff line numberDiff line change
@@ -43,14 +43,20 @@ static ColumnRef CreateTerminalColumn(const TypeAst& ast) {
4343
case Type::Int64:
4444
return std::make_shared<ColumnInt64>();
4545

46-
case Type::UUID:
47-
return std::make_shared<ColumnUUID>();
48-
4946
case Type::Float32:
5047
return std::make_shared<ColumnFloat32>();
5148
case Type::Float64:
5249
return std::make_shared<ColumnFloat64>();
5350

51+
case Type::Decimal:
52+
return std::make_shared<ColumnDecimal>(ast.elements.front().value, ast.elements.back().value);
53+
case Type::Decimal32:
54+
return std::make_shared<ColumnDecimal>(9, ast.elements.front().value);
55+
case Type::Decimal64:
56+
return std::make_shared<ColumnDecimal>(18, ast.elements.front().value);
57+
case Type::Decimal128:
58+
return std::make_shared<ColumnDecimal>(38, ast.elements.front().value);
59+
5460
case Type::String:
5561
return std::make_shared<ColumnString>();
5662
case Type::FixedString:
@@ -61,23 +67,14 @@ static ColumnRef CreateTerminalColumn(const TypeAst& ast) {
6167
case Type::Date:
6268
return std::make_shared<ColumnDate>();
6369

64-
case Type::Decimal32:
65-
return std::make_shared<ColumnDecimal>(9, ast.elements.front().value);
66-
case Type::Decimal64:
67-
return std::make_shared<ColumnDecimal>(18, ast.elements.front().value);
68-
case Type::Decimal128:
69-
if (ast.elements.size() == 2) {
70-
return std::make_shared<ColumnDecimal>(ast.elements.front().value, ast.elements.back().value);
71-
} else if (ast.elements.size() == 1) {
72-
return std::make_shared<ColumnDecimal>(38, ast.elements.front().value);
73-
}
74-
throw std::runtime_error("Unexpected branch in code");
75-
7670
case Type::IPv4:
7771
return std::make_shared<ColumnIPv4>();
7872
case Type::IPv6:
7973
return std::make_shared<ColumnIPv6>();
8074

75+
case Type::UUID:
76+
return std::make_shared<ColumnUUID>();
77+
8178
default:
8279
return nullptr;
8380
}

clickhouse/columns/numeric.cpp

+1-2
Original file line numberDiff line numberDiff line change
@@ -69,15 +69,14 @@ template class ColumnVector<int8_t>;
6969
template class ColumnVector<int16_t>;
7070
template class ColumnVector<int32_t>;
7171
template class ColumnVector<int64_t>;
72-
template class ColumnVector<__int128>;
7372

7473
template class ColumnVector<uint8_t>;
7574
template class ColumnVector<uint16_t>;
7675
template class ColumnVector<uint32_t>;
7776
template class ColumnVector<uint64_t>;
77+
template class ColumnVector<Int128>;
7878

7979
template class ColumnVector<float>;
8080
template class ColumnVector<double>;
8181

8282
}
83-

clickhouse/columns/numeric.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ class ColumnVector : public Column {
4848
std::vector<T> data_;
4949
};
5050

51+
using Int128 = __int128;
52+
5153
using ColumnUInt8 = ColumnVector<uint8_t>;
5254
using ColumnUInt16 = ColumnVector<uint16_t>;
5355
using ColumnUInt32 = ColumnVector<uint32_t>;
@@ -57,7 +59,7 @@ using ColumnInt8 = ColumnVector<int8_t>;
5759
using ColumnInt16 = ColumnVector<int16_t>;
5860
using ColumnInt32 = ColumnVector<int32_t>;
5961
using ColumnInt64 = ColumnVector<int64_t>;
60-
using ColumnInt128 = ColumnVector<__int128>;
62+
using ColumnInt128 = ColumnVector<Int128>;
6163

6264
using ColumnFloat32 = ColumnVector<float>;
6365
using ColumnFloat64 = ColumnVector<double>;

clickhouse/types/type_parser.cpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,12 @@ static const std::unordered_map<std::string, Type::Code> kTypeCode = {
2828
{ "Enum8", Type::Enum8 },
2929
{ "Enum16", Type::Enum16 },
3030
{ "UUID", Type::UUID },
31+
{ "IPv4", Type::IPv4 },
32+
{ "IPv6", Type::IPv6 },
33+
{ "Decimal", Type::Decimal },
3134
{ "Decimal32", Type::Decimal32 },
3235
{ "Decimal64", Type::Decimal64 },
3336
{ "Decimal128", Type::Decimal128 },
34-
{ "Decimal", Type::Decimal128 },
35-
{ "IPv4", Type::IPv4 },
36-
{ "IPv6", Type::IPv6 },
3737
};
3838

3939
static Type::Code GetTypeCode(const std::string& name) {

clickhouse/types/type_parser.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ struct TypeAst {
3131
int64_t value = 0;
3232
/// Subelements of the type.
3333
/// Used to store enum's names and values as well.
34-
std::list<TypeAst> elements;
34+
std::vector<TypeAst> elements;
3535
};
3636

3737

clickhouse/types/types.cpp

+18-25
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ std::string Type::GetName() const {
5656
case Enum8:
5757
case Enum16:
5858
return As<EnumType>()->GetName();
59+
case Decimal:
5960
case Decimal32:
6061
case Decimal64:
6162
case Decimal128:
@@ -78,6 +79,10 @@ TypeRef Type::CreateDateTime() {
7879
return TypeRef(new Type(Type::DateTime));
7980
}
8081

82+
TypeRef Type::CreateDecimal(size_t precision, size_t scale) {
83+
return TypeRef(new DecimalType(precision, scale));
84+
}
85+
8186
TypeRef Type::CreateIPv4() {
8287
return TypeRef(new Type(Type::IPv4));
8388
}
@@ -118,10 +123,6 @@ TypeRef Type::CreateUUID() {
118123
return TypeRef(new Type(Type::UUID));
119124
}
120125

121-
TypeRef Type::CreateDecimal(size_t precision, size_t scale) {
122-
return TypeRef(new DecimalType(precision, scale));
123-
}
124-
125126
/// class ArrayType
126127

127128
ArrayType::ArrayType(TypeRef item_type) : Type(Array), item_type_(item_type) {
@@ -130,34 +131,26 @@ ArrayType::ArrayType(TypeRef item_type) : Type(Array), item_type_(item_type) {
130131
/// class DecimalType
131132

132133
DecimalType::DecimalType(size_t precision, size_t scale)
133-
: Type([&] {
134-
if (precision <= 9) {
135-
return Type::Decimal32;
136-
} else if (precision <= 18) {
137-
return Type::Decimal64;
138-
} else {
139-
return Type::Decimal128;
140-
}
141-
}()),
134+
: Type(Decimal),
142135
precision_(precision),
143136
scale_(scale) {
144137
// TODO: assert(precision <= 38 && precision > 0);
145138
}
146139

147140
std::string DecimalType::GetName() const {
148-
std::string result = "Decimal";
149-
150-
if (precision_ <= 9) {
151-
result += "32";
152-
} else if (precision_ <= 18) {
153-
result += "64";
154-
} else {
155-
result += "128";
141+
switch (GetCode()) {
142+
case Decimal:
143+
return "Decimal(" + std::to_string(precision_) + "," + std::to_string(scale_) + ")";
144+
case Decimal32:
145+
return "Decimal32(" + std::to_string(scale_) + ")";
146+
case Decimal64:
147+
return "Decimal64(" + std::to_string(scale_) + ")";
148+
case Decimal128:
149+
return "Decimal128(" + std::to_string(scale_) + ")";
150+
default:
151+
/// XXX: NOT REACHED!
152+
return "";
156153
}
157-
158-
result += "(" + std::to_string(scale_) + ")";
159-
160-
return result;
161154
}
162155

163156
/// class EnumType

clickhouse/types/types.h

+6-5
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ class Type {
1717
Int16,
1818
Int32,
1919
Int64,
20-
Int128,
2120
UInt8,
2221
UInt16,
2322
UInt32,
@@ -34,11 +33,13 @@ class Type {
3433
Enum8,
3534
Enum16,
3635
UUID,
36+
IPv4,
37+
IPv6,
38+
Int128,
39+
Decimal,
3740
Decimal32,
3841
Decimal64,
3942
Decimal128,
40-
IPv4,
41-
IPv6,
4243
};
4344

4445
using EnumItem = std::pair<std::string /* name */, int16_t /* value */>;
@@ -73,6 +74,8 @@ class Type {
7374

7475
static TypeRef CreateDateTime();
7576

77+
static TypeRef CreateDecimal(size_t precision, size_t scale);
78+
7679
static TypeRef CreateIPv4();
7780

7881
static TypeRef CreateIPv6();
@@ -96,8 +99,6 @@ class Type {
9699

97100
static TypeRef CreateUUID();
98101

99-
static TypeRef CreateDecimal(size_t precision, size_t scale);
100-
101102
private:
102103
const Code code_;
103104
};

0 commit comments

Comments
 (0)