2015-01-26 15:27:51 +00:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <DB/Core/ErrorCodes.h>
|
2015-01-26 16:53:44 +00:00
|
|
|
#include <Poco/Util/AbstractConfiguration.h>
|
2015-01-26 15:27:51 +00:00
|
|
|
#include <vector>
|
|
|
|
#include <string>
|
2015-01-27 13:00:20 +00:00
|
|
|
#include <map>
|
2015-01-26 15:27:51 +00:00
|
|
|
|
|
|
|
namespace DB
|
|
|
|
{
|
|
|
|
|
2015-02-10 14:50:43 +00:00
|
|
|
enum class AttributeType
|
2015-01-27 13:00:20 +00:00
|
|
|
{
|
|
|
|
uint8,
|
|
|
|
uint16,
|
|
|
|
uint32,
|
|
|
|
uint64,
|
|
|
|
int8,
|
|
|
|
int16,
|
|
|
|
int32,
|
|
|
|
int64,
|
|
|
|
float32,
|
|
|
|
float64,
|
|
|
|
string
|
|
|
|
};
|
|
|
|
|
2015-02-10 14:50:43 +00:00
|
|
|
inline AttributeType getAttributeTypeByName(const std::string & type)
|
2015-01-27 13:00:20 +00:00
|
|
|
{
|
2015-02-10 14:50:43 +00:00
|
|
|
static const std::unordered_map<std::string, AttributeType> dictionary{
|
|
|
|
{ "UInt8", AttributeType::uint8 },
|
|
|
|
{ "UInt16", AttributeType::uint16 },
|
|
|
|
{ "UInt32", AttributeType::uint32 },
|
|
|
|
{ "UInt64", AttributeType::uint64 },
|
|
|
|
{ "Int8", AttributeType::int8 },
|
|
|
|
{ "Int16", AttributeType::int16 },
|
|
|
|
{ "Int32", AttributeType::int32 },
|
|
|
|
{ "Int64", AttributeType::int64 },
|
|
|
|
{ "Float32", AttributeType::float32 },
|
|
|
|
{ "Float64", AttributeType::float64 },
|
|
|
|
{ "String", AttributeType::string },
|
2015-01-27 13:00:20 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
const auto it = dictionary.find(type);
|
|
|
|
if (it != std::end(dictionary))
|
|
|
|
return it->second;
|
|
|
|
|
|
|
|
throw Exception{
|
|
|
|
"Unknown type " + type,
|
|
|
|
ErrorCodes::UNKNOWN_TYPE
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2015-02-10 14:50:43 +00:00
|
|
|
inline std::string toString(const AttributeType type)
|
2015-01-28 13:20:20 +00:00
|
|
|
{
|
|
|
|
switch (type)
|
|
|
|
{
|
2015-02-10 14:50:43 +00:00
|
|
|
case AttributeType::uint8: return "UInt8";
|
|
|
|
case AttributeType::uint16: return "UInt16";
|
|
|
|
case AttributeType::uint32: return "UInt32";
|
|
|
|
case AttributeType::uint64: return "UInt64";
|
|
|
|
case AttributeType::int8: return "Int8";
|
|
|
|
case AttributeType::int16: return "Int16";
|
|
|
|
case AttributeType::int32: return "Int32";
|
|
|
|
case AttributeType::int64: return "Int64";
|
|
|
|
case AttributeType::float32: return "Float32";
|
|
|
|
case AttributeType::float64: return "Float64";
|
|
|
|
case AttributeType::string: return "String";
|
2015-01-28 13:20:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
throw Exception{
|
2015-02-10 14:50:43 +00:00
|
|
|
"Unknown attribute_type " + toString(static_cast<int>(type)),
|
2015-01-28 13:20:20 +00:00
|
|
|
ErrorCodes::ARGUMENT_OUT_OF_BOUND
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2015-02-10 14:50:43 +00:00
|
|
|
/// Min and max lifetimes for a dictionary or it's entry
|
2015-01-30 15:18:13 +00:00
|
|
|
struct DictionaryLifetime
|
|
|
|
{
|
|
|
|
std::uint64_t min_sec;
|
|
|
|
std::uint64_t max_sec;
|
|
|
|
|
2015-02-10 14:50:43 +00:00
|
|
|
DictionaryLifetime(const Poco::Util::AbstractConfiguration & config, const std::string & config_prefix)
|
2015-01-30 15:18:13 +00:00
|
|
|
{
|
|
|
|
const auto & lifetime_min_key = config_prefix + ".min";
|
|
|
|
const auto has_min = config.has(lifetime_min_key);
|
2015-02-10 14:50:43 +00:00
|
|
|
|
|
|
|
this->min_sec = has_min ? config.getInt(lifetime_min_key) : config.getInt(config_prefix);
|
|
|
|
this->max_sec = has_min ? config.getInt(config_prefix + ".max") : this->min_sec;
|
2015-01-30 15:18:13 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2015-02-10 14:50:43 +00:00
|
|
|
/** Holds the description of a single dictionary attribute:
|
|
|
|
* - name, used for lookup into dictionary and source;
|
|
|
|
* - type, used in conjunction with DataTypeFactory and getAttributeTypeByname;
|
|
|
|
* - null_value, used as a default value for non-existent entries in the dictionary,
|
|
|
|
* decimal representation for numeric attributes;
|
|
|
|
* - hierarchical, whether this attribute defines a hierarchy;
|
|
|
|
* - injective, whether the mapping to parent is injective (can be used for optimization of GROUP BY?)
|
|
|
|
*/
|
2015-01-26 15:27:51 +00:00
|
|
|
struct DictionaryAttribute
|
|
|
|
{
|
|
|
|
std::string name;
|
|
|
|
std::string type;
|
|
|
|
std::string null_value;
|
|
|
|
bool hierarchical;
|
|
|
|
bool injective;
|
|
|
|
};
|
|
|
|
|
2015-02-10 14:50:43 +00:00
|
|
|
/// Name of identifier plus list of attributes
|
2015-01-26 15:27:51 +00:00
|
|
|
struct DictionaryStructure
|
|
|
|
{
|
|
|
|
std::string id_name;
|
|
|
|
std::vector<DictionaryAttribute> attributes;
|
|
|
|
|
2015-02-10 14:50:43 +00:00
|
|
|
DictionaryStructure(const Poco::Util::AbstractConfiguration & config, const std::string & config_prefix)
|
|
|
|
: id_name{config.getString(config_prefix + ".id.name")}
|
2015-01-26 15:27:51 +00:00
|
|
|
{
|
|
|
|
if (id_name.empty())
|
|
|
|
throw Exception{
|
|
|
|
"No 'id' specified for dictionary",
|
|
|
|
ErrorCodes::BAD_ARGUMENTS
|
|
|
|
};
|
|
|
|
|
|
|
|
Poco::Util::AbstractConfiguration::Keys keys;
|
|
|
|
config.keys(config_prefix, keys);
|
|
|
|
auto has_hierarchy = false;
|
2015-02-10 14:50:43 +00:00
|
|
|
|
2015-01-26 15:27:51 +00:00
|
|
|
for (const auto & key : keys)
|
|
|
|
{
|
|
|
|
if (0 != strncmp(key.data(), "attribute", strlen("attribute")))
|
|
|
|
continue;
|
|
|
|
|
2015-02-10 14:50:43 +00:00
|
|
|
const auto prefix = config_prefix + '.' + key + '.';
|
|
|
|
const auto name = config.getString(prefix + "name");
|
|
|
|
const auto type = config.getString(prefix + "type");
|
|
|
|
const auto null_value = config.getString(prefix + "null_value");
|
2015-01-26 15:27:51 +00:00
|
|
|
const auto hierarchical = config.getBool(prefix + "hierarchical", false);
|
|
|
|
const auto injective = config.getBool(prefix + "injective", false);
|
|
|
|
if (name.empty() || type.empty())
|
|
|
|
throw Exception{
|
|
|
|
"Properties 'name' and 'type' of an attribute cannot be empty",
|
|
|
|
ErrorCodes::BAD_ARGUMENTS
|
|
|
|
};
|
|
|
|
|
|
|
|
if (has_hierarchy && hierarchical)
|
|
|
|
throw Exception{
|
|
|
|
"Only one hierarchical attribute supported",
|
|
|
|
ErrorCodes::BAD_ARGUMENTS
|
|
|
|
};
|
|
|
|
|
|
|
|
has_hierarchy = has_hierarchy || hierarchical;
|
|
|
|
|
2015-02-10 14:50:43 +00:00
|
|
|
attributes.emplace_back(DictionaryAttribute{
|
|
|
|
name, type, null_value, hierarchical, injective
|
|
|
|
});
|
2015-01-26 15:27:51 +00:00
|
|
|
}
|
|
|
|
|
2015-02-10 14:50:43 +00:00
|
|
|
if (attributes.empty())
|
2015-01-26 15:27:51 +00:00
|
|
|
throw Exception{
|
|
|
|
"Dictionary has no attributes defined",
|
|
|
|
ErrorCodes::BAD_ARGUMENTS
|
|
|
|
};
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
}
|