| 1 | #include "DictionarySourceFactory.h" | 
|---|
| 2 |  | 
|---|
| 3 | #include <Columns/ColumnsNumber.h> | 
|---|
| 4 | #include <Core/Block.h> | 
|---|
| 5 | #include <Core/ColumnWithTypeAndName.h> | 
|---|
| 6 | #include <DataTypes/DataTypeNullable.h> | 
|---|
| 7 | #include <DataTypes/DataTypesNumber.h> | 
|---|
| 8 | #include <Poco/Logger.h> | 
|---|
| 9 | #include <common/logger_useful.h> | 
|---|
| 10 | #include "DictionaryStructure.h" | 
|---|
| 11 |  | 
|---|
| 12 | namespace DB | 
|---|
| 13 | { | 
|---|
| 14 | namespace ErrorCodes | 
|---|
| 15 | { | 
|---|
| 16 | extern const int UNKNOWN_ELEMENT_IN_CONFIG; | 
|---|
| 17 | extern const int EXCESSIVE_ELEMENT_IN_CONFIG; | 
|---|
| 18 | extern const int LOGICAL_ERROR; | 
|---|
| 19 | extern const int SUPPORT_IS_DISABLED; | 
|---|
| 20 | } | 
|---|
| 21 |  | 
|---|
| 22 | namespace | 
|---|
| 23 | { | 
|---|
| 24 | Block createSampleBlock(const DictionaryStructure & dict_struct) | 
|---|
| 25 | { | 
|---|
| 26 | Block block; | 
|---|
| 27 |  | 
|---|
| 28 | if (dict_struct.id) | 
|---|
| 29 | block.insert(ColumnWithTypeAndName{ColumnUInt64::create(1, 0), std::make_shared<DataTypeUInt64>(), dict_struct.id->name}); | 
|---|
| 30 |  | 
|---|
| 31 | if (dict_struct.key) | 
|---|
| 32 | { | 
|---|
| 33 | for (const auto & attribute : *dict_struct.key) | 
|---|
| 34 | { | 
|---|
| 35 | auto column = attribute.type->createColumn(); | 
|---|
| 36 | column->insertDefault(); | 
|---|
| 37 |  | 
|---|
| 38 | block.insert(ColumnWithTypeAndName{std::move(column), attribute.type, attribute.name}); | 
|---|
| 39 | } | 
|---|
| 40 | } | 
|---|
| 41 |  | 
|---|
| 42 | if (dict_struct.range_min) | 
|---|
| 43 | { | 
|---|
| 44 | for (const auto & attribute : {dict_struct.range_min, dict_struct.range_max}) | 
|---|
| 45 | { | 
|---|
| 46 | const auto & type = std::make_shared<DataTypeNullable>(attribute->type); | 
|---|
| 47 | auto column = type->createColumn(); | 
|---|
| 48 | column->insertDefault(); | 
|---|
| 49 |  | 
|---|
| 50 | block.insert(ColumnWithTypeAndName{std::move(column), type, attribute->name}); | 
|---|
| 51 | } | 
|---|
| 52 | } | 
|---|
| 53 |  | 
|---|
| 54 | for (const auto & attribute : dict_struct.attributes) | 
|---|
| 55 | { | 
|---|
| 56 | auto column = attribute.type->createColumn(); | 
|---|
| 57 | column->insert(attribute.null_value); | 
|---|
| 58 |  | 
|---|
| 59 | block.insert(ColumnWithTypeAndName{std::move(column), attribute.type, attribute.name}); | 
|---|
| 60 | } | 
|---|
| 61 |  | 
|---|
| 62 | return block; | 
|---|
| 63 | } | 
|---|
| 64 |  | 
|---|
| 65 | } | 
|---|
| 66 |  | 
|---|
| 67 |  | 
|---|
| 68 | DictionarySourceFactory::DictionarySourceFactory() : log(&Poco::Logger::get( "DictionarySourceFactory")) | 
|---|
| 69 | { | 
|---|
| 70 | } | 
|---|
| 71 |  | 
|---|
| 72 | void DictionarySourceFactory::registerSource(const std::string & source_type, Creator create_source) | 
|---|
| 73 | { | 
|---|
| 74 | if (!registered_sources.emplace(source_type, std::move(create_source)).second) | 
|---|
| 75 | throw Exception( "DictionarySourceFactory: the source name '"+ source_type + "' is not unique", ErrorCodes::LOGICAL_ERROR); | 
|---|
| 76 | } | 
|---|
| 77 |  | 
|---|
| 78 | DictionarySourcePtr DictionarySourceFactory::create( | 
|---|
| 79 | const std::string & name, | 
|---|
| 80 | const Poco::Util::AbstractConfiguration & config, | 
|---|
| 81 | const std::string & config_prefix, | 
|---|
| 82 | const DictionaryStructure & dict_struct, | 
|---|
| 83 | const Context & context, | 
|---|
| 84 | bool check_config) const | 
|---|
| 85 | { | 
|---|
| 86 | Poco::Util::AbstractConfiguration::Keys keys; | 
|---|
| 87 | config.keys(config_prefix, keys); | 
|---|
| 88 | if (keys.size() != 1) | 
|---|
| 89 | throw Exception{name + ": element dictionary.source should have exactly one child element", | 
|---|
| 90 | ErrorCodes::EXCESSIVE_ELEMENT_IN_CONFIG}; | 
|---|
| 91 |  | 
|---|
| 92 | const auto & source_type = keys.front(); | 
|---|
| 93 |  | 
|---|
| 94 | const auto found = registered_sources.find(source_type); | 
|---|
| 95 | if (found != registered_sources.end()) | 
|---|
| 96 | { | 
|---|
| 97 | const auto & create_source = found->second; | 
|---|
| 98 | auto sample_block = createSampleBlock(dict_struct); | 
|---|
| 99 | return create_source(dict_struct, config, config_prefix, sample_block, context, check_config); | 
|---|
| 100 | } | 
|---|
| 101 |  | 
|---|
| 102 | throw Exception{name + ": unknown dictionary source type: "+ source_type, ErrorCodes::UNKNOWN_ELEMENT_IN_CONFIG}; | 
|---|
| 103 | } | 
|---|
| 104 |  | 
|---|
| 105 | DictionarySourceFactory & DictionarySourceFactory::instance() | 
|---|
| 106 | { | 
|---|
| 107 | static DictionarySourceFactory instance; | 
|---|
| 108 | return instance; | 
|---|
| 109 | } | 
|---|
| 110 |  | 
|---|
| 111 | } | 
|---|
| 112 |  | 
|---|