1#include <Functions/IFunctionImpl.h>
2#include <Functions/FunctionFactory.h>
3#include <Functions/FunctionHelpers.h>
4#include <DataTypes/DataTypeString.h>
5#include <Columns/ColumnString.h>
6#include <Interpreters/Context.h>
7#include <Common/Macros.h>
8#include <Core/Field.h>
9
10
11namespace DB
12{
13
14namespace ErrorCodes
15{
16 extern const int ILLEGAL_TYPE_OF_ARGUMENT;
17 extern const int ILLEGAL_COLUMN;
18}
19
20/** Get the value of macro from configuration file.
21 * For example, it may be used as a sophisticated replacement for the function 'hostName' if servers have complicated hostnames
22 * but you still need to distinguish them by some convenient names.
23 */
24class FunctionGetMacro : public IFunction
25{
26private:
27 MultiVersion<Macros>::Version macros;
28
29public:
30 static constexpr auto name = "getMacro";
31 static FunctionPtr create(const Context & context)
32 {
33 return std::make_shared<FunctionGetMacro>(context.getMacros());
34 }
35
36 FunctionGetMacro(MultiVersion<Macros>::Version macros_) : macros(std::move(macros_)) {}
37
38 String getName() const override
39 {
40 return name;
41 }
42
43 bool isDeterministic() const override { return false; }
44
45 bool isDeterministicInScopeOfQuery() const override
46 {
47 return false;
48 }
49
50 size_t getNumberOfArguments() const override
51 {
52 return 1;
53 }
54
55 DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
56 {
57 if (!isString(arguments[0]))
58 throw Exception("The argument of function " + getName() + " must have String type", ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
59 return std::make_shared<DataTypeString>();
60 }
61
62 /** convertToFullColumn needed because in distributed query processing,
63 * each server returns its own value.
64 */
65 void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result, size_t input_rows_count) override
66 {
67 const IColumn * arg_column = block.getByPosition(arguments[0]).column.get();
68 const ColumnString * arg_string = checkAndGetColumnConstData<ColumnString>(arg_column);
69
70 if (!arg_string)
71 throw Exception("The argument of function " + getName() + " must be constant String", ErrorCodes::ILLEGAL_COLUMN);
72
73 block.getByPosition(result).column = block.getByPosition(result).type->createColumnConst(
74 input_rows_count, macros->getValue(arg_string->getDataAt(0).toString()))->convertToFullColumnIfConst();
75 }
76};
77
78
79void registerFunctionGetMacro(FunctionFactory & factory)
80{
81 factory.registerFunction<FunctionGetMacro>();
82}
83
84}
85