dbms: ExternalDictionaries: remove most invididual getters

This commit is contained in:
Andrey Mironov 2015-07-10 17:43:49 +03:00
parent 8ce8b602b6
commit 8ea2990e7d
5 changed files with 39 additions and 202 deletions

View File

@ -87,61 +87,11 @@ public:
bool hasHierarchy() const override { return hierarchical_attribute; } bool hasHierarchy() const override { return hierarchical_attribute; }
id_t toParent(const id_t id) const override
{
PODArray<UInt64> ids{1, id};
PODArray<UInt64> out{1};
getItems<UInt64>(*hierarchical_attribute, ids, out);
return out.front();
}
void toParent(const PODArray<id_t> & ids, PODArray<id_t> & out) const override void toParent(const PODArray<id_t> & ids, PODArray<id_t> & out) const override
{ {
getItems<UInt64>(*hierarchical_attribute, ids, out); getItems<UInt64>(*hierarchical_attribute, ids, out);
} }
#define DECLARE_INDIVIDUAL_GETTER(TYPE) \
TYPE get##TYPE(const std::string & attribute_name, const id_t id) const override\
{\
auto & attribute = getAttribute(attribute_name);\
if (attribute.type != AttributeUnderlyingType::TYPE)\
throw Exception{\
"Type mismatch: attribute " + attribute_name + " has type " + toString(attribute.type),\
ErrorCodes::TYPE_MISMATCH\
};\
\
PODArray<UInt64> ids{1, id};\
PODArray<TYPE> out{1};\
getItems<TYPE>(attribute, ids, out);\
return out.front();\
}
DECLARE_INDIVIDUAL_GETTER(UInt8)
DECLARE_INDIVIDUAL_GETTER(UInt16)
DECLARE_INDIVIDUAL_GETTER(UInt32)
DECLARE_INDIVIDUAL_GETTER(UInt64)
DECLARE_INDIVIDUAL_GETTER(Int8)
DECLARE_INDIVIDUAL_GETTER(Int16)
DECLARE_INDIVIDUAL_GETTER(Int32)
DECLARE_INDIVIDUAL_GETTER(Int64)
DECLARE_INDIVIDUAL_GETTER(Float32)
DECLARE_INDIVIDUAL_GETTER(Float64)
#undef DECLARE_INDIVIDUAL_GETTER
String getString(const std::string & attribute_name, const id_t id) const override
{
auto & attribute = getAttribute(attribute_name);
if (attribute.type != AttributeUnderlyingType::String)
throw Exception{
"Type mismatch: attribute " + attribute_name + " has type " + toString(attribute.type),
ErrorCodes::TYPE_MISMATCH
};
PODArray<UInt64> ids{1, id};
ColumnString out;
getItems(attribute, ids, &out);
return String{out.getDataAt(0)};
};
#define DECLARE_MULTIPLE_GETTER(TYPE)\ #define DECLARE_MULTIPLE_GETTER(TYPE)\
void get##TYPE(const std::string & attribute_name, const PODArray<id_t> & ids, PODArray<TYPE> & out) const override\ void get##TYPE(const std::string & attribute_name, const PODArray<id_t> & ids, PODArray<TYPE> & out) const override\
{\ {\

View File

@ -81,64 +81,11 @@ public:
bool hasHierarchy() const override { return hierarchical_attribute; } bool hasHierarchy() const override { return hierarchical_attribute; }
id_t toParent(const id_t id) const override
{
const auto attr = hierarchical_attribute;
const auto & array = *std::get<std::unique_ptr<PODArray<UInt64>>>(attr->arrays);
query_count.fetch_add(1, std::memory_order_relaxed);
return id < array.size() ? array[id] : std::get<UInt64>(attr->null_values);
}
void toParent(const PODArray<id_t> & ids, PODArray<id_t> & out) const override void toParent(const PODArray<id_t> & ids, PODArray<id_t> & out) const override
{ {
getItems<UInt64>(*hierarchical_attribute, ids, out); getItems<UInt64>(*hierarchical_attribute, ids, out);
} }
#define DECLARE_INDIVIDUAL_GETTER(TYPE) \
TYPE get##TYPE(const std::string & attribute_name, const id_t id) const override\
{\
const auto & attribute = getAttribute(attribute_name);\
if (attribute.type != AttributeUnderlyingType::TYPE)\
throw Exception{\
"Type mismatch: attribute " + attribute_name + " has type " + toString(attribute.type),\
ErrorCodes::TYPE_MISMATCH\
};\
\
const auto & array = *std::get<std::unique_ptr<PODArray<TYPE>>>(attribute.arrays);\
\
query_count.fetch_add(1, std::memory_order_relaxed);\
\
return id < array.size() ? array[id] : std::get<TYPE>(attribute.null_values);\
}
DECLARE_INDIVIDUAL_GETTER(UInt8)
DECLARE_INDIVIDUAL_GETTER(UInt16)
DECLARE_INDIVIDUAL_GETTER(UInt32)
DECLARE_INDIVIDUAL_GETTER(UInt64)
DECLARE_INDIVIDUAL_GETTER(Int8)
DECLARE_INDIVIDUAL_GETTER(Int16)
DECLARE_INDIVIDUAL_GETTER(Int32)
DECLARE_INDIVIDUAL_GETTER(Int64)
DECLARE_INDIVIDUAL_GETTER(Float32)
DECLARE_INDIVIDUAL_GETTER(Float64)
#undef DECLARE_INDIVIDUAL_GETTER
String getString(const std::string & attribute_name, const id_t id) const override
{
const auto & attribute = getAttribute(attribute_name);
if (attribute.type != AttributeUnderlyingType::String)
throw Exception{
"Type mismatch: attribute " + attribute_name + " has type " + toString(attribute.type),
ErrorCodes::TYPE_MISMATCH
};
const auto & array = *std::get<std::unique_ptr<PODArray<StringRef>>>(attribute.arrays);
query_count.fetch_add(1, std::memory_order_relaxed);
return id < array.size() ? String{array[id]} : std::get<String>(attribute.null_values);
}
#define DECLARE_MULTIPLE_GETTER(TYPE)\ #define DECLARE_MULTIPLE_GETTER(TYPE)\
void get##TYPE(const std::string & attribute_name, const PODArray<id_t> & ids, PODArray<TYPE> & out) const override\ void get##TYPE(const std::string & attribute_name, const PODArray<id_t> & ids, PODArray<TYPE> & out) const override\
{\ {\

View File

@ -10,6 +10,7 @@
#include <memory> #include <memory>
#include <tuple> #include <tuple>
namespace DB namespace DB
{ {
@ -78,67 +79,11 @@ public:
bool hasHierarchy() const override { return hierarchical_attribute; } bool hasHierarchy() const override { return hierarchical_attribute; }
id_t toParent(const id_t id) const override
{
const auto attr = hierarchical_attribute;
const auto & map = *std::get<std::unique_ptr<HashMap<UInt64, UInt64>>>(attr->maps);
const auto it = map.find(id);
query_count.fetch_add(1, std::memory_order_relaxed);
return it != map.end() ? it->second : std::get<UInt64>(attr->null_values);
}
void toParent(const PODArray<id_t> & ids, PODArray<id_t> & out) const override void toParent(const PODArray<id_t> & ids, PODArray<id_t> & out) const override
{ {
getItems<UInt64>(*hierarchical_attribute, ids, out); getItems<UInt64>(*hierarchical_attribute, ids, out);
} }
#define DECLARE_INDIVIDUAL_GETTER(TYPE) \
TYPE get##TYPE(const std::string & attribute_name, const id_t id) const override\
{\
const auto & attribute = getAttribute(attribute_name);\
if (attribute.type != AttributeUnderlyingType::TYPE)\
throw Exception{\
"Type mismatch: attribute " + attribute_name + " has type " + toString(attribute.type),\
ErrorCodes::TYPE_MISMATCH\
};\
\
const auto & map = *std::get<std::unique_ptr<HashMap<UInt64, TYPE>>>(attribute.maps);\
const auto it = map.find(id);\
\
query_count.fetch_add(1, std::memory_order_relaxed);\
\
return it != map.end() ? TYPE{it->second} : std::get<TYPE>(attribute.null_values);\
}
DECLARE_INDIVIDUAL_GETTER(UInt8)
DECLARE_INDIVIDUAL_GETTER(UInt16)
DECLARE_INDIVIDUAL_GETTER(UInt32)
DECLARE_INDIVIDUAL_GETTER(UInt64)
DECLARE_INDIVIDUAL_GETTER(Int8)
DECLARE_INDIVIDUAL_GETTER(Int16)
DECLARE_INDIVIDUAL_GETTER(Int32)
DECLARE_INDIVIDUAL_GETTER(Int64)
DECLARE_INDIVIDUAL_GETTER(Float32)
DECLARE_INDIVIDUAL_GETTER(Float64)
#undef DECLARE_INDIVIDUAL_GETTER
String getString(const std::string & attribute_name, const id_t id) const override
{
const auto & attribute = getAttribute(attribute_name);
if (attribute.type != AttributeUnderlyingType::String)
throw Exception{
"Type mismatch: attribute " + attribute_name + " has type " + toString(attribute.type),
ErrorCodes::TYPE_MISMATCH
};
const auto & map = *std::get<std::unique_ptr<HashMap<UInt64, StringRef>>>(attribute.maps);
const auto it = map.find(id);
query_count.fetch_add(1, std::memory_order_relaxed);
return it != map.end() ? String{it->second} : std::get<String>(attribute.null_values);
}
#define DECLARE_MULTIPLE_GETTER(TYPE)\ #define DECLARE_MULTIPLE_GETTER(TYPE)\
void get##TYPE(const std::string & attribute_name, const PODArray<id_t> & ids, PODArray<TYPE> & out) const override\ void get##TYPE(const std::string & attribute_name, const PODArray<id_t> & ids, PODArray<TYPE> & out) const override\
{\ {\

View File

@ -56,7 +56,16 @@ public:
virtual bool hasHierarchy() const = 0; virtual bool hasHierarchy() const = 0;
/// do not call unless you ensure that hasHierarchy() returns true /// do not call unless you ensure that hasHierarchy() returns true
virtual id_t toParent(id_t id) const = 0; id_t toParent(id_t id) const
{
const PODArray<UInt64> ids(1, id);
PODArray<UInt64> out(1);
toParent(ids, out);
return out.front();
}
virtual void toParent(const PODArray<id_t> & ids, PODArray<id_t> & out) const = 0; virtual void toParent(const PODArray<id_t> & ids, PODArray<id_t> & out) const = 0;
bool in(id_t child_id, const id_t ancestor_id) const bool in(id_t child_id, const id_t ancestor_id) const
@ -67,20 +76,7 @@ public:
return child_id != 0; return child_id != 0;
} }
/// functions for individual access /// return mapped values for a collection of identifiers
virtual UInt8 getUInt8(const std::string & attribute_name, id_t id) const = 0;
virtual UInt16 getUInt16(const std::string & attribute_name, id_t id) const = 0;
virtual UInt32 getUInt32(const std::string & attribute_name, id_t id) const = 0;
virtual UInt64 getUInt64(const std::string & attribute_name, id_t id) const = 0;
virtual Int8 getInt8(const std::string & attribute_name, id_t id) const = 0;
virtual Int16 getInt16(const std::string & attribute_name, id_t id) const = 0;
virtual Int32 getInt32(const std::string & attribute_name, id_t id) const = 0;
virtual Int64 getInt64(const std::string & attribute_name, id_t id) const = 0;
virtual Float32 getFloat32(const std::string & attribute_name, id_t id) const = 0;
virtual Float64 getFloat64(const std::string & attribute_name, id_t id) const = 0;
virtual String getString(const std::string & attribute_name, id_t id) const = 0;
/// functions for multiple access
virtual void getUInt8(const std::string & attr_name, const PODArray<id_t> & ids, PODArray<UInt8> & out) const = 0; virtual void getUInt8(const std::string & attr_name, const PODArray<id_t> & ids, PODArray<UInt8> & out) const = 0;
virtual void getUInt16(const std::string & attr_name, const PODArray<id_t> & ids, PODArray<UInt16> & out) const = 0; virtual void getUInt16(const std::string & attr_name, const PODArray<id_t> & ids, PODArray<UInt16> & out) const = 0;
virtual void getUInt32(const std::string & attr_name, const PODArray<id_t> & ids, PODArray<UInt32> & out) const = 0; virtual void getUInt32(const std::string & attr_name, const PODArray<id_t> & ids, PODArray<UInt32> & out) const = 0;

View File

@ -839,9 +839,12 @@ private:
} }
else if (const auto id_col = typeid_cast<const ColumnConst<UInt64> *>(id_col_untyped)) else if (const auto id_col = typeid_cast<const ColumnConst<UInt64> *>(id_col_untyped))
{ {
const PODArray<UInt64> ids{1, id_col->getData()};
auto out = std::make_unique<ColumnString>();
dictionary->getString(attr_name, ids, out.get());
block.getByPosition(result).column = new ColumnConst<String>{ block.getByPosition(result).column = new ColumnConst<String>{
id_col->size(), id_col->size(), out->getDataAtWithTerminatingZero(0).toString()
dictionary->getString(attr_name, id_col->getData())
}; };
} }
else else
@ -863,10 +866,6 @@ template <typename DataType> struct DictGetTraits;
#define DECLARE_DICT_GET_TRAITS(TYPE, DATA_TYPE) \ #define DECLARE_DICT_GET_TRAITS(TYPE, DATA_TYPE) \
template <> struct DictGetTraits<DATA_TYPE>\ template <> struct DictGetTraits<DATA_TYPE>\
{\ {\
static TYPE get(const IDictionary * const dict, const std::string & name, const IDictionary::id_t id)\
{\
return dict->get##TYPE(name, id);\
}\
static void get(const IDictionary * const dict, const std::string & name, const PODArray<IDictionary::id_t> & ids, PODArray<TYPE> & out)\ static void get(const IDictionary * const dict, const std::string & name, const PODArray<IDictionary::id_t> & ids, PODArray<TYPE> & out)\
{\ {\
dict->get##TYPE(name, ids, out);\ dict->get##TYPE(name, ids, out);\
@ -996,10 +995,11 @@ private:
} }
else if (const auto id_col = typeid_cast<const ColumnConst<UInt64> *>(id_col_untyped)) else if (const auto id_col = typeid_cast<const ColumnConst<UInt64> *>(id_col_untyped))
{ {
block.getByPosition(result).column = new ColumnConst<Type>{ const PODArray<UInt64> ids{1, id_col->getData()};
id_col->size(), PODArray<Type> data(1);
DictGetTraits<DataType>::get(dictionary, attr_name, id_col->getData()) DictGetTraits<DataType>::get(dictionary, attr_name, ids, data);
};
block.getByPosition(result).column = new ColumnConst<Type>{id_col->size(), data.front()};
} }
else else
{ {
@ -1113,10 +1113,7 @@ private:
if (!dict) if (!dict)
return false; return false;
const auto id_col_untyped = block.getByPosition(arguments[1]).column.get(); const auto get_hierarchies = [&] (const PODArray<UInt64> & in, PODArray<UInt64> & out, PODArray<UInt64> & offsets) {
if (const auto id_col = typeid_cast<const ColumnVector<UInt64> *>(id_col_untyped))
{
const auto & in = id_col->getData();
const auto size = in.size(); const auto size = in.size();
/// copy of `in` array /// copy of `in` array
@ -1157,12 +1154,6 @@ private:
std::swap(in_array, out_array); std::swap(in_array, out_array);
} }
const auto backend = new ColumnVector<UInt64>;
const auto array = new ColumnArray{backend};
block.getByPosition(result).column = array;
auto & out = backend->getData();
auto & offsets = array->getOffsets();
out.reserve(total_count); out.reserve(total_count);
offsets.resize(size); offsets.resize(size);
@ -1172,21 +1163,29 @@ private:
out.insert_assume_reserved(std::begin(ids), std::end(ids)); out.insert_assume_reserved(std::begin(ids), std::end(ids));
offsets[i] = out.size(); offsets[i] = out.size();
} }
};
const auto id_col_untyped = block.getByPosition(arguments[1]).column.get();
if (const auto id_col = typeid_cast<const ColumnVector<UInt64> *>(id_col_untyped))
{
const auto & in = id_col->getData();
const auto backend = new ColumnVector<UInt64>;
const auto array = new ColumnArray{backend};
block.getByPosition(result).column = array;
get_hierarchies(in, backend->getData(), array->getOffsets());
} }
else if (const auto id_col = typeid_cast<const ColumnConst<UInt64> *>(id_col_untyped)) else if (const auto id_col = typeid_cast<const ColumnConst<UInt64> *>(id_col_untyped))
{ {
Array res; const PODArray<UInt64> in(1, id_col->getData());
const auto backend = new ColumnVector<UInt64>;
const auto array = new ColumnArray{backend};
IDictionary::id_t cur = id_col->getData(); get_hierarchies(in, backend->getData(), array->getOffsets());
while (cur)
{
res.push_back(cur);
cur = dictionary->toParent(cur);
}
block.getByPosition(result).column = new ColumnConstArray{ block.getByPosition(result).column = new ColumnConstArray{
id_col->size(), id_col->size(),
res, (*array)[0].get<Array>(),
new DataTypeArray{new DataTypeUInt64} new DataTypeArray{new DataTypeUInt64}
}; };
} }