Skip to content

Commit

Permalink
#32 add support of enums
Browse files Browse the repository at this point in the history
  • Loading branch information
artpaul committed Oct 18, 2017
1 parent ea6d21f commit 0d4b1eb
Show file tree
Hide file tree
Showing 15 changed files with 410 additions and 21 deletions.
17 changes: 7 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,16 @@ C++ client for [Yandex ClickHouse](https://clickhouse.yandex/)

## Supported data types

* UInt8, UInt16, UInt32, UInt64, Int8, Int16, Int32, Int64
* Float32, Float64
* String
* FixedString(N)
* DateTime
* Date
* Array(T)
* Date
* DateTime
* Enum8, Enum16
* FixedString(N)
* Float32, Float64
* Nullable(T)
* String
* Tuple
* UInt8, UInt16, UInt32, UInt64, Int8, Int16, Int32, Int64

## Building

Expand Down Expand Up @@ -68,7 +69,3 @@ client.Select("SELECT id, name FROM test.numbers", [] (const Block& block)
/// Delete table.
client.Execute("DROP TABLE test.numbers");
```

## Disclaimer

Library currently is under development and it interface is subject to change.
1 change: 1 addition & 0 deletions clickhouse/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ ADD_LIBRARY (clickhouse-cpp-lib

columns/array.cpp
columns/date.cpp
columns/enum.cpp
columns/factory.cpp
columns/nullable.cpp
columns/numeric.cpp
Expand Down
6 changes: 5 additions & 1 deletion clickhouse/base/string_view.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,13 +88,17 @@ class StringViewImpl {
return StringViewImpl(data_ + pos, count);
}

inline const std::basic_string<TChar> to_string() const {
return std::basic_string<TChar>(data_, size_);
}

public:
inline operator bool () const noexcept {
return !empty();
}

inline explicit operator const std::basic_string<TChar> () const {
return std::basic_string<TChar>(data_, size_);
return to_string();
}

inline TChar operator [] (size_type pos) const noexcept {
Expand Down
1 change: 1 addition & 0 deletions clickhouse/client.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

#include "columns/array.h"
#include "columns/date.h"
#include "columns/enum.h"
#include "columns/nullable.h"
#include "columns/numeric.h"
#include "columns/string.h"
Expand Down
91 changes: 91 additions & 0 deletions clickhouse/columns/enum.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
#include "enum.h"
#include "utils.h"

namespace clickhouse {

template <typename T>
ColumnEnum<T>::ColumnEnum(TypeRef type)
: Column(type)
{
}

template <typename T>
ColumnEnum<T>::ColumnEnum(TypeRef type, const std::vector<T>& data)
: Column(type)
, data_(data)
{
}

template <typename T>
void ColumnEnum<T>::Append(const T& value, bool checkValue) {
if (checkValue) {
// TODO type_->HasEnumValue(value), "Enum type doesn't have value " + std::to_string(value);
}
data_.push_back(value);
}

template <typename T>
void ColumnEnum<T>::Append(const std::string& name) {
data_.push_back(EnumType(type_).GetEnumValue(name));
}

template <typename T>
const T& ColumnEnum<T>::At(size_t n) const {
return data_.at(n);
}

template <typename T>
const std::string ColumnEnum<T>::NameAt(size_t n) const {
return EnumType(type_).GetEnumName(data_.at(n));
}

template <typename T>
const T& ColumnEnum<T>::operator[] (size_t n) const {
return data_[n];
}

template <typename T>
void ColumnEnum<T>::SetAt(size_t n, const T& value, bool checkValue) {
if (checkValue) {
// TODO: type_->HasEnumValue(value), "Enum type doesn't have value " + std::to_string(value);
}
data_.at(n) = value;
}

template <typename T>
void ColumnEnum<T>::SetNameAt(size_t n, const std::string& name) {
data_.at(n) = EnumType(type_).GetEnumValue(name);
}

template <typename T>
void ColumnEnum<T>::Append(ColumnRef column) {
if (auto col = column->As<ColumnEnum<T>>()) {
data_.insert(data_.end(), col->data_.begin(), col->data_.end());
}
}

template <typename T>
bool ColumnEnum<T>::Load(CodedInputStream* input, size_t rows) {
data_.resize(rows);
return input->ReadRaw(data_.data(), data_.size() * sizeof(T));
}

template <typename T>
void ColumnEnum<T>::Save(CodedOutputStream* output) {
output->WriteRaw(data_.data(), data_.size() * sizeof(T));
}

template <typename T>
size_t ColumnEnum<T>::Size() const {
return data_.size();
}

template <typename T>
ColumnRef ColumnEnum<T>::Slice(size_t begin, size_t len) {
return std::make_shared<ColumnEnum<T>>(type_, SliceVector(data_, begin, len));
}

template class ColumnEnum<int8_t>;
template class ColumnEnum<int16_t>;

}
52 changes: 52 additions & 0 deletions clickhouse/columns/enum.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#pragma once

#include "column.h"

namespace clickhouse {


template <typename T>
class ColumnEnum : public Column {
public:
ColumnEnum(TypeRef type);
ColumnEnum(TypeRef type, const std::vector<T>& data);

/// Appends one element to the end of column.
void Append(const T& value, bool checkValue = false);
void Append(const std::string& name);

/// Returns element at given row number.
const T& At(size_t n) const;
const std::string NameAt(size_t n) const;

/// Returns element at given row number.
const T& operator[] (size_t n) const;

/// Set element at given row number.
void SetAt(size_t n, const T& value, bool checkValue = false);
void SetNameAt(size_t n, const std::string& name);

public:
/// Appends content of given column to the end of current one.
void Append(ColumnRef column) override;

/// Loads column data from input stream.
bool Load(CodedInputStream* input, size_t rows) override;

/// Saves column data to output stream.
void Save(CodedOutputStream* output) override;

/// Returns count of rows in the column.
size_t Size() const override;

/// Makes slice of the current column.
ColumnRef Slice(size_t begin, size_t len) override;

private:
std::vector<T> data_;
};

using ColumnEnum8 = ColumnEnum<int8_t>;
using ColumnEnum16 = ColumnEnum<int16_t>;

}
23 changes: 22 additions & 1 deletion clickhouse/columns/factory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include "array.h"
#include "date.h"
#include "enum.h"
#include "nullable.h"
#include "numeric.h"
#include "string.h"
Expand Down Expand Up @@ -39,7 +40,7 @@ static ColumnRef CreateTerminalColumn(const TypeAst& ast) {
if (ast.name == "String")
return std::make_shared<ColumnString>();
if (ast.name == "FixedString")
return std::make_shared<ColumnFixedString>(ast.elements.front().size);
return std::make_shared<ColumnFixedString>(ast.elements.front().value);

if (ast.name == "DateTime")
return std::make_shared<ColumnDateTime>();
Expand Down Expand Up @@ -82,6 +83,26 @@ static ColumnRef CreateColumnFromAst(const TypeAst& ast) {
return std::make_shared<ColumnTuple>(columns);
}

case TypeAst::Enum: {
std::vector<Type::EnumItem> enum_items;

for (const auto& elem : ast.elements) {
enum_items.push_back(
Type::EnumItem{elem.name.to_string(), (int16_t)elem.value});
}

if (ast.name == "Enum8") {
return std::make_shared<ColumnEnum8>(
Type::CreateEnum8(enum_items)
);
} else if (ast.name == "Enum16") {
return std::make_shared<ColumnEnum16>(
Type::CreateEnum16(enum_items)
);
}
break;
}

case TypeAst::Null:
case TypeAst::Number:
break;
Expand Down
18 changes: 13 additions & 5 deletions clickhouse/types/type_parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ static TypeAst::Meta GetTypeMeta(const StringView& name) {
return TypeAst::Tuple;
}

if (name == "Enum8" || name == "Enum16") {
return TypeAst::Enum;
}

return TypeAst::Terminal;
}

Expand Down Expand Up @@ -49,7 +53,7 @@ bool TypeParser::Parse(TypeAst* type) {
break;
case Token::Number:
type_->meta = TypeAst::Number;
type_->size = FromString<int>(token.value);
type_->value = FromString<int>(token.value);
break;
case Token::LPar:
type_->elements.emplace_back(TypeAst());
Expand Down Expand Up @@ -84,6 +88,10 @@ TypeParser::Token TypeParser::NextToken() {
case '\0':
continue;

case '=':
case '\'':
continue;

case '(':
return Token{Token::LPar, StringView(cur_++, 1)};
case ')':
Expand All @@ -94,18 +102,18 @@ TypeParser::Token TypeParser::NextToken() {
default: {
const char* st = cur_;

if (isalpha(*cur_)) {
if (isalpha(*cur_) || *cur_ == '_') {
for (; cur_ < end_; ++cur_) {
if (!isalpha(*cur_) && !isdigit(*cur_)) {
if (!isalpha(*cur_) && !isdigit(*cur_) && *cur_ != '_') {
break;
}
}

return Token{Token::Name, StringView(st, cur_)};
}

if (isdigit(*cur_)) {
for (; cur_ < end_; ++cur_) {
if (isdigit(*cur_) || *cur_ == '-') {
for (++cur_; cur_ < end_; ++cur_) {
if (!isdigit(*cur_)) {
break;
}
Expand Down
7 changes: 5 additions & 2 deletions clickhouse/types/type_parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,18 @@ struct TypeAst {
Number,
Terminal,
Tuple,
Enum
};

/// Type's category.
Meta meta;
/// Type's name.
StringView name;
/// Size of type's instance. For fixed-width types only.
size_t size = 0;
/// Value associated with the node,
/// used for fixed-width types and enum values.
int64_t value = 0;
/// Subelements of the type.
/// Used to store enum's names and values as well.
std::list<TypeAst> elements;
};

Expand Down
Loading

0 comments on commit 0d4b1eb

Please sign in to comment.