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