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
12namespace DB
13{
14namespace 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
22namespace
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
68DictionarySourceFactory::DictionarySourceFactory() : log(&Poco::Logger::get("DictionarySourceFactory"))
69{
70}
71
72void 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
78DictionarySourcePtr 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
105DictionarySourceFactory & DictionarySourceFactory::instance()
106{
107 static DictionarySourceFactory instance;
108 return instance;
109}
110
111}
112