| 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 | |