Skip to content

Commit 077fe6f

Browse files
authored
Merge pull request #50 from Enmk/DateTime64
Add DateTime64 data type.
2 parents 4ceb5d1 + 4dd948b commit 077fe6f

17 files changed

+538
-58
lines changed

.gitignore

+4
Original file line numberDiff line numberDiff line change
@@ -274,3 +274,7 @@ BUCKAROO_DEPS
274274

275275
# Visual Studio Code
276276
/.vscode/
277+
278+
# Vim
279+
*.swp
280+
*.swo

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ C++ client for [Yandex ClickHouse](https://clickhouse.yandex/)
77

88
* Array(T)
99
* Date
10-
* DateTime
10+
* DateTime, DateTime64
1111
* Decimal32, Decimal64, Decimal128
1212
* Enum8, Enum16
1313
* FixedString(N)

clickhouse/columns/date.cpp

+69
Original file line numberDiff line numberDiff line change
@@ -113,4 +113,73 @@ ItemView ColumnDateTime::GetItem(size_t index) const {
113113
return data_->GetItem(index);
114114
}
115115

116+
ColumnDateTime64::ColumnDateTime64(size_t precision)
117+
: ColumnDateTime64(Type::CreateDateTime64(precision), std::make_shared<ColumnDecimal>(18ul, precision))
118+
{}
119+
120+
ColumnDateTime64::ColumnDateTime64(TypeRef type, std::shared_ptr<ColumnDecimal> data)
121+
: Column(type),
122+
data_(data),
123+
precision_(type->As<DateTime64Type>()->GetPrecision())
124+
{}
125+
126+
void ColumnDateTime64::Append(const Int64& value) {
127+
// TODO: we need a type, which safely represents datetime.
128+
// The precision of Poco.DateTime is not big enough.
129+
data_->Append(value);
130+
}
131+
132+
//void ColumnDateTime64::Append(const std::string& value) {
133+
// data_->Append(value);
134+
//}
135+
136+
Int64 ColumnDateTime64::At(size_t n) const {
137+
return data_->At(n);
138+
}
139+
140+
void ColumnDateTime64::Append(ColumnRef column) {
141+
if (auto col = column->As<ColumnDateTime64>()) {
142+
data_->Append(col->data_);
143+
}
144+
}
145+
146+
bool ColumnDateTime64::Load(CodedInputStream* input, size_t rows) {
147+
return data_->Load(input, rows);
148+
}
149+
150+
void ColumnDateTime64::Save(CodedOutputStream* output) {
151+
data_->Save(output);
152+
}
153+
154+
void ColumnDateTime64::Clear() {
155+
data_->Clear();
156+
}
157+
size_t ColumnDateTime64::Size() const {
158+
return data_->Size();
159+
}
160+
161+
ItemView ColumnDateTime64::GetItem(size_t index) const {
162+
return data_->GetItem(index);
163+
}
164+
165+
void ColumnDateTime64::Swap(Column& other) {
166+
auto& col = dynamic_cast<ColumnDateTime64&>(other);
167+
if (col.GetPrecision() != GetPrecision()) {
168+
throw std::runtime_error("Can't swap DateTime64 columns when precisions are not the same: "
169+
+ std::to_string(GetPrecision()) + "(this) != " + std::to_string(col.GetPrecision()) + "(that)");
170+
}
171+
172+
data_.swap(col.data_);
173+
}
174+
175+
ColumnRef ColumnDateTime64::Slice(size_t begin, size_t len) {
176+
auto sliced_data = data_->Slice(begin, len)->As<ColumnDecimal>();
177+
178+
return ColumnRef{new ColumnDateTime64(type_, sliced_data)};
179+
}
180+
181+
size_t ColumnDateTime64::GetPrecision() const {
182+
return precision_;
183+
}
184+
116185
}

clickhouse/columns/date.h

+49
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#pragma once
22

3+
#include "decimal.h"
34
#include "numeric.h"
45

56
#include <ctime>
@@ -82,4 +83,52 @@ class ColumnDateTime : public Column {
8283
std::shared_ptr<ColumnUInt32> data_;
8384
};
8485

86+
87+
/** */
88+
class ColumnDateTime64 : public Column {
89+
public:
90+
explicit ColumnDateTime64(size_t);
91+
92+
/// Appends one element to the end of column.
93+
void Append(const Int64& value);
94+
// It is a bit controversal: users might expect it to parse string of ISO8601 or some other human-friendly format,
95+
// but current implemntation parses it as fractional integer with decimal point, e.g. "123.456".
96+
// void Append(const std::string& value);
97+
98+
/// Returns element at given row number.
99+
Int64 At(size_t n) const;
100+
101+
public:
102+
/// Appends content of given column to the end of current one.
103+
void Append(ColumnRef column) override;
104+
105+
/// Loads column data from input stream.
106+
bool Load(CodedInputStream* input, size_t rows) override;
107+
108+
/// Clear column data .
109+
void Clear() override;
110+
111+
/// Saves column data to output stream.
112+
void Save(CodedOutputStream* output) override;
113+
114+
/// Returns count of rows in the column.
115+
size_t Size() const override;
116+
117+
/// Makes slice of the current column.
118+
ColumnRef Slice(size_t begin, size_t len) override;
119+
120+
void Swap(Column& other) override;
121+
122+
ItemView GetItem(size_t index) const override;
123+
124+
size_t GetPrecision() const;
125+
126+
private:
127+
ColumnDateTime64(TypeRef type, std::shared_ptr<ColumnDecimal> data);
128+
129+
private:
130+
std::shared_ptr<ColumnDecimal> data_;
131+
const size_t precision_;
132+
};
133+
85134
}

clickhouse/columns/decimal.cpp

+24-13
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
#include "decimal.h"
22

3-
#include <iostream>
4-
53
namespace clickhouse {
64

75
ColumnDecimal::ColumnDecimal(size_t precision, size_t scale)
@@ -16,8 +14,9 @@ ColumnDecimal::ColumnDecimal(size_t precision, size_t scale)
1614
}
1715
}
1816

19-
ColumnDecimal::ColumnDecimal(TypeRef type)
20-
: Column(type)
17+
ColumnDecimal::ColumnDecimal(TypeRef type, ColumnRef data)
18+
: Column(type),
19+
data_(data)
2120
{
2221
}
2322

@@ -83,12 +82,15 @@ void ColumnDecimal::Append(const std::string& value) {
8382
}
8483

8584
Int128 ColumnDecimal::At(size_t i) const {
86-
if (data_->Type()->GetCode() == Type::Int32) {
87-
return static_cast<Int128>(data_->As<ColumnInt32>()->At(i));
88-
} else if (data_->Type()->GetCode() == Type::Int64) {
89-
return static_cast<Int128>(data_->As<ColumnInt64>()->At(i));
90-
} else {
91-
return data_->As<ColumnInt128>()->At(i);
85+
switch (data_->Type()->GetCode()) {
86+
case Type::Int32:
87+
return static_cast<Int128>(data_->As<ColumnInt32>()->At(i));
88+
case Type::Int64:
89+
return static_cast<Int128>(data_->As<ColumnInt64>()->At(i));
90+
case Type::Int128:
91+
return data_->As<ColumnInt128>()->At(i);
92+
default:
93+
throw std::runtime_error("Invalid data_ column type in ColumnDecimal");
9294
}
9395
}
9496

@@ -115,9 +117,8 @@ size_t ColumnDecimal::Size() const {
115117
}
116118

117119
ColumnRef ColumnDecimal::Slice(size_t begin, size_t len) {
118-
std::shared_ptr<ColumnDecimal> slice(new ColumnDecimal(type_));
119-
slice->data_ = data_->Slice(begin, len);
120-
return slice;
120+
// coundn't use std::make_shared since this c-tor is private
121+
return ColumnRef{new ColumnDecimal(type_, data_->Slice(begin, len))};
121122
}
122123

123124
void ColumnDecimal::Swap(Column& other) {
@@ -129,4 +130,14 @@ ItemView ColumnDecimal::GetItem(size_t index) const {
129130
return data_->GetItem(index);
130131
}
131132

133+
size_t ColumnDecimal::GetScale() const
134+
{
135+
return type_->As<DecimalType>()->GetScale();
136+
}
137+
138+
size_t ColumnDecimal::GetPrecision() const
139+
{
140+
return type_->As<DecimalType>()->GetPrecision();
141+
}
142+
132143
}

clickhouse/columns/decimal.h

+4-1
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,17 @@ class ColumnDecimal : public Column {
2727
void Swap(Column& other) override;
2828
ItemView GetItem(size_t index) const override;
2929

30+
size_t GetScale() const;
31+
size_t GetPrecision() const;
32+
3033
private:
3134
/// Depending on a precision it can be one of:
3235
/// - ColumnInt32
3336
/// - ColumnInt64
3437
/// - ColumnInt128
3538
ColumnRef data_;
3639

37-
explicit ColumnDecimal(TypeRef type); // for `Slice(…)`
40+
explicit ColumnDecimal(TypeRef type, ColumnRef data);
3841
};
3942

4043
}

clickhouse/columns/factory.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ static ColumnRef CreateTerminalColumn(const TypeAst& ast) {
6565

6666
case Type::DateTime:
6767
return std::make_shared<ColumnDateTime>();
68+
case Type::DateTime64:
69+
return std::make_shared<ColumnDateTime64>(ast.elements.front().value);
6870
case Type::Date:
6971
return std::make_shared<ColumnDate>();
7072

clickhouse/columns/itemview.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ void ItemView::ValidateData(Type::Code type, DataType data) {
2020
ANY, /*String*/
2121
ANY, /*FixedString*/
2222
4, /*DateTime*/
23+
8, /*DateTime64*/
2324
2, /*Date*/
2425
ERR, /*Array*/
2526
ERR, /*Nullable*/

clickhouse/columns/numeric.cpp

+8-1
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,19 @@ ColumnVector<T>::ColumnVector()
1010
}
1111

1212
template <typename T>
13-
ColumnVector<T>::ColumnVector(const std::vector<T>& data)
13+
ColumnVector<T>::ColumnVector(const std::vector<T> & data)
1414
: Column(Type::CreateSimple<T>())
1515
, data_(data)
1616
{
1717
}
1818

19+
template <typename T>
20+
ColumnVector<T>::ColumnVector(std::vector<T> && data)
21+
: Column(Type::CreateSimple<T>())
22+
, data_(std::move(data))
23+
{
24+
}
25+
1926
template <typename T>
2027
void ColumnVector<T>::Append(const T& value) {
2128
data_.push_back(value);

clickhouse/columns/numeric.h

+2
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ class ColumnVector : public Column {
1515
ColumnVector();
1616

1717
explicit ColumnVector(const std::vector<T>& data);
18+
explicit ColumnVector(std::vector<T> && data);
1819

1920
/// Appends one element to the end of column.
2021
void Append(const T& value);
@@ -54,6 +55,7 @@ class ColumnVector : public Column {
5455
};
5556

5657
using Int128 = __int128;
58+
using Int64 = int64_t;
5759

5860
using ColumnUInt8 = ColumnVector<uint8_t>;
5961
using ColumnUInt16 = ColumnVector<uint16_t>;

clickhouse/types/type_parser.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ static const std::unordered_map<std::string, Type::Code> kTypeCode = {
3030
{ "String", Type::String },
3131
{ "FixedString", Type::FixedString },
3232
{ "DateTime", Type::DateTime },
33+
{ "DateTime64", Type::DateTime64 },
3334
{ "Date", Type::Date },
3435
{ "Array", Type::Array },
3536
{ "Nullable", Type::Nullable },

clickhouse/types/types.cpp

+25
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ std::string Type::GetName() const {
4545
return "IPv6";
4646
case DateTime:
4747
return "DateTime";
48+
case DateTime64:
49+
return As<DateTime64Type>()->GetName();
4850
case Date:
4951
return "Date";
5052
case Array:
@@ -81,6 +83,10 @@ TypeRef Type::CreateDateTime() {
8183
return TypeRef(new Type(Type::DateTime));
8284
}
8385

86+
TypeRef Type::CreateDateTime64(size_t precision) {
87+
return TypeRef(new DateTime64Type(precision));
88+
}
89+
8490
TypeRef Type::CreateDecimal(size_t precision, size_t scale) {
8591
return TypeRef(new DecimalType(precision, scale));
8692
}
@@ -219,6 +225,25 @@ EnumType::ValueToNameIterator EnumType::EndValueToName() const {
219225
return value_to_name_.end();
220226
}
221227

228+
/// class DateTime64Type
229+
230+
DateTime64Type::DateTime64Type(size_t precision)
231+
: Type(DateTime64), precision_(precision) {
232+
233+
if (precision_ > 18) {
234+
throw std::runtime_error("DateTime64 precision is > 18");
235+
}
236+
}
237+
238+
std::string DateTime64Type::GetName() const {
239+
std::string datetime64_representation;
240+
datetime64_representation.reserve(14);
241+
datetime64_representation += "DateTime64(";
242+
datetime64_representation += std::to_string(precision_);
243+
datetime64_representation += ")";
244+
return datetime64_representation;
245+
}
246+
222247
/// class FixedStringType
223248

224249
FixedStringType::FixedStringType(size_t n) : Type(FixedString), size_(n) {

clickhouse/types/types.h

+16
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ class Type {
4141
Decimal64,
4242
Decimal128,
4343
LowCardinality,
44+
DateTime64,
4445
};
4546

4647
using EnumItem = std::pair<std::string /* name */, int16_t /* value */>;
@@ -76,6 +77,8 @@ class Type {
7677

7778
static TypeRef CreateDateTime();
7879

80+
static TypeRef CreateDateTime64(size_t precision);
81+
7982
static TypeRef CreateDecimal(size_t precision, size_t scale);
8083

8184
static TypeRef CreateIPv4();
@@ -139,11 +142,24 @@ class DecimalType : public Type {
139142
std::string GetName() const;
140143

141144
inline size_t GetScale() const { return scale_; }
145+
inline size_t GetPrecision() const { return precision_; }
142146

143147
private:
144148
const size_t precision_, scale_;
145149
};
146150

151+
class DateTime64Type: public Type {
152+
public:
153+
explicit DateTime64Type(size_t precision);
154+
155+
std::string GetName() const;
156+
157+
inline size_t GetPrecision() const { return precision_; }
158+
159+
private:
160+
size_t precision_;
161+
};
162+
147163
class EnumType : public Type {
148164
public:
149165
EnumType(Type::Code type, const std::vector<EnumItem>& items);

0 commit comments

Comments
 (0)