Skip to content

Commit 9ed5193

Browse files
committed
Add support for Decimal column types
1 parent 175a5e2 commit 9ed5193

18 files changed

+414
-66
lines changed

.clang-format

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,7 @@ AccessModifierOffset: -4
55
AlignConsecutiveAssignments: true
66
AllowShortFunctionsOnASingleLine: InlineOnly
77
ColumnLimit: 140
8+
DerivePointerAlignment: false
89
FixNamespaceComments: true
9-
IndentWidth: 4
10+
IndentWidth: 4
11+
PointerAlignment: Left

clickhouse/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ ADD_LIBRARY (clickhouse-cpp-lib
88

99
columns/array.cpp
1010
columns/date.cpp
11+
columns/decimal.cpp
1112
columns/enum.cpp
1213
columns/factory.cpp
1314
columns/nullable.cpp

clickhouse/client.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,8 @@ Client::Impl::Impl(const ClientOptions& opts)
165165
, buffered_output_(&socket_output_)
166166
, output_(&buffered_output_)
167167
{
168+
// TODO: throw on big-endianness of platform
169+
168170
for (int i = 0; ; ) {
169171
try {
170172
ResetConnection();

clickhouse/client.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
#include "columns/array.h"
77
#include "columns/date.h"
8+
#include "columns/decimal.h"
89
#include "columns/enum.h"
910
#include "columns/nullable.h"
1011
#include "columns/numeric.h"

clickhouse/columns/column.h

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

3-
#include "../base/input.h"
43
#include "../base/coded.h"
4+
#include "../base/input.h"
55
#include "../types/types.h"
66

77
namespace clickhouse {
@@ -11,24 +11,19 @@ using ColumnRef = std::shared_ptr<class Column>;
1111
/**
1212
* An abstract base of all columns classes.
1313
*/
14-
class Column : public std::enable_shared_from_this<Column>
15-
{
14+
class Column : public std::enable_shared_from_this<Column> {
1615
public:
17-
explicit inline Column(TypeRef type)
18-
: type_(type)
19-
{
20-
}
16+
explicit inline Column(TypeRef type) : type_(type) {}
2117

22-
virtual ~Column()
23-
{ }
18+
virtual ~Column() {}
2419

25-
/// Downcast pointer to the specific culumn's subtype.
20+
/// Downcast pointer to the specific column's subtype.
2621
template <typename T>
2722
inline std::shared_ptr<T> As() {
2823
return std::dynamic_pointer_cast<T>(shared_from_this());
2924
}
3025

31-
/// Downcast pointer to the specific culumn's subtype.
26+
/// Downcast pointer to the specific column's subtype.
3227
template <typename T>
3328
inline std::shared_ptr<const T> As() const {
3429
return std::dynamic_pointer_cast<const T>(shared_from_this());
@@ -45,7 +40,7 @@ class Column : public std::enable_shared_from_this<Column>
4540

4641
/// Saves column data to output stream.
4742
virtual void Save(CodedOutputStream* output) = 0;
48-
43+
4944
/// Clear column data .
5045
virtual void Clear() = 0;
5146

@@ -59,4 +54,4 @@ class Column : public std::enable_shared_from_this<Column>
5954
TypeRef type_;
6055
};
6156

62-
}
57+
} // namespace clickhouse

clickhouse/columns/decimal.cpp

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
#include "decimal.h"
2+
3+
#include "numeric.h"
4+
5+
namespace clickhouse {
6+
7+
ColumnDecimal::ColumnDecimal(size_t precision, size_t scale) : Column(Type::CreateDecimal(precision, scale)) {
8+
if (precision <= 9) {
9+
data_ = ColumnRef(new ColumnInt32());
10+
} else if (precision <= 18) {
11+
data_ = ColumnRef(new ColumnInt64());
12+
} else {
13+
data_ = ColumnRef(new ColumnInt128());
14+
}
15+
}
16+
17+
void ColumnDecimal::Append(const Int128& value) {
18+
if (data_->Type()->GetCode() == Type::Int32) {
19+
data_->As<ColumnInt32>()->Append(static_cast<ColumnInt32::DataType>(value));
20+
} else if (data_->Type()->GetCode() == Type::Int64) {
21+
data_->As<ColumnInt64>()->Append(static_cast<ColumnInt64::DataType>(value));
22+
} else {
23+
data_->As<ColumnInt128>()->Append(static_cast<ColumnInt128::DataType>(value));
24+
}
25+
}
26+
27+
void ColumnDecimal::Append(const std::string &value) {
28+
Int128 int_value = 0;
29+
auto c = value.begin();
30+
bool sign = true;
31+
32+
while (c != value.end()) {
33+
if (*c == '-') {
34+
sign = false;
35+
if (c != value.begin()) {
36+
break;
37+
}
38+
} else if (*c == '.') {
39+
// TODO: compare distance with `scale`
40+
} else if (*c >= '0' && *c <= '9') {
41+
int_value = int_value * 10 + (*c - '0');
42+
} else {
43+
// TODO: throw exception on unexpected symbol
44+
}
45+
++c;
46+
}
47+
48+
if (c != value.end()) {
49+
// TODO: throw exception about symbols after 'minus'
50+
}
51+
52+
Append(sign ? int_value : -int_value);
53+
}
54+
55+
Int128 ColumnDecimal::At(size_t i) const {
56+
if (data_->Type()->GetCode() == Type::Int32) {
57+
return static_cast<Int128>(data_->As<ColumnInt32>()->At(i));
58+
} else if (data_->Type()->GetCode() == Type::Int64) {
59+
return static_cast<Int128>(data_->As<ColumnInt64>()->At(i));
60+
} else {
61+
return data_->As<ColumnInt128>()->At(i);
62+
}
63+
}
64+
65+
ColumnRef ColumnDecimal::Slice(size_t begin, size_t len) {
66+
std::shared_ptr<ColumnDecimal> slice(new ColumnDecimal(Type()));
67+
slice->data_ = data_->Slice(begin, len);
68+
return slice;
69+
}
70+
71+
ColumnDecimal::ColumnDecimal(TypeRef type) : Column(type) {
72+
}
73+
74+
} // namespace clickhouse

clickhouse/columns/decimal.h

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
#pragma once
2+
3+
#include "column.h"
4+
5+
namespace clickhouse {
6+
7+
using Int128 = __int128;
8+
9+
/**
10+
* Represents a column of decimal type.
11+
*/
12+
13+
class ColumnDecimal : public Column {
14+
public:
15+
ColumnDecimal(size_t precision, size_t scale);
16+
17+
void Append(const Int128& value);
18+
void Append(const std::string& value);
19+
20+
Int128 At(size_t i) const;
21+
22+
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(); }
28+
ColumnRef Slice(size_t begin, size_t len) override;
29+
30+
private:
31+
/// Depending on a precision it can be one of:
32+
/// - ColumnInt32
33+
/// - ColumnInt64
34+
/// - ColumnInt128
35+
ColumnRef data_;
36+
37+
explicit ColumnDecimal(TypeRef type); // for `Slice(…)`
38+
};
39+
40+
} // namespace clickhouse

clickhouse/columns/factory.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
#include "array.h"
44
#include "date.h"
5+
#include "decimal.h"
56
#include "enum.h"
67
#include "nullable.h"
78
#include "numeric.h"
@@ -52,6 +53,17 @@ static ColumnRef CreateTerminalColumn(const TypeAst& ast) {
5253
case Type::Date:
5354
return std::make_shared<ColumnDate>();
5455

56+
case Type::Decimal32:
57+
return std::make_shared<ColumnDecimal>(9, ast.elements.front().value);
58+
case Type::Decimal64:
59+
return std::make_shared<ColumnDecimal>(18, ast.elements.front().value);
60+
case Type::Decimal128:
61+
if (ast.elements.size() == 2) {
62+
return std::make_shared<ColumnDecimal>(ast.elements.front().value, ast.elements.back().value);
63+
} else if (ast.elements.size() == 1) {
64+
return std::make_shared<ColumnDecimal>(38, ast.elements.front().value);
65+
}
66+
5567
default:
5668
return nullptr;
5769
}

clickhouse/columns/numeric.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ 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>;
7273

7374
template class ColumnVector<uint8_t>;
7475
template class ColumnVector<uint16_t>;

clickhouse/columns/numeric.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ namespace clickhouse {
1010
template <typename T>
1111
class ColumnVector : public Column {
1212
public:
13+
using DataType = T;
14+
1315
ColumnVector();
1416

1517
explicit ColumnVector(const std::vector<T>& data);
@@ -55,6 +57,7 @@ using ColumnInt8 = ColumnVector<int8_t>;
5557
using ColumnInt16 = ColumnVector<int16_t>;
5658
using ColumnInt32 = ColumnVector<int32_t>;
5759
using ColumnInt64 = ColumnVector<int64_t>;
60+
using ColumnInt128 = ColumnVector<__int128>;
5861

5962
using ColumnFloat32 = ColumnVector<float>;
6063
using ColumnFloat64 = ColumnVector<double>;

clickhouse/types/type_parser.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ static const std::unordered_map<std::string, Type::Code> kTypeCode = {
2626
{ "Enum8", Type::Enum8 },
2727
{ "Enum16", Type::Enum16 },
2828
{ "UUID", Type::UUID },
29+
{ "Decimal32", Type::Decimal32 },
30+
{ "Decimal64", Type::Decimal64 },
31+
{ "Decimal128", Type::Decimal128 },
32+
{ "Decimal", Type::Decimal128 },
2933
};
3034

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

clickhouse/types/type_parser.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ struct TypeAst {
1717
Number,
1818
Terminal,
1919
Tuple,
20-
Enum
20+
Enum,
2121
};
2222

2323
/// Type's category.

0 commit comments

Comments
 (0)