1#if defined(__ELF__) && !defined(__FreeBSD__)
2
3#include <Common/SymbolIndex.h>
4#include <Columns/ColumnString.h>
5#include <Columns/ColumnsNumber.h>
6#include <DataTypes/DataTypeString.h>
7#include <Functions/IFunctionImpl.h>
8#include <Functions/FunctionHelpers.h>
9#include <Functions/FunctionFactory.h>
10#include <Interpreters/Context.h>
11#include <IO/WriteHelpers.h>
12
13
14namespace DB
15{
16
17namespace ErrorCodes
18{
19 extern const int ILLEGAL_COLUMN;
20 extern const int ILLEGAL_TYPE_OF_ARGUMENT;
21 extern const int NUMBER_OF_ARGUMENTS_DOESNT_MATCH;
22 extern const int FUNCTION_NOT_ALLOWED;
23}
24
25class FunctionAddressToSymbol : public IFunction
26{
27public:
28 static constexpr auto name = "addressToSymbol";
29 static FunctionPtr create(const Context & context)
30 {
31 if (!context.getSettingsRef().allow_introspection_functions)
32 throw Exception("Introspection functions are disabled, because setting 'allow_introspection_functions' is set to 0", ErrorCodes::FUNCTION_NOT_ALLOWED);
33 return std::make_shared<FunctionAddressToSymbol>();
34 }
35
36 String getName() const override
37 {
38 return name;
39 }
40
41 size_t getNumberOfArguments() const override
42 {
43 return 1;
44 }
45
46 DataTypePtr getReturnTypeImpl(const ColumnsWithTypeAndName & arguments) const override
47 {
48 if (arguments.size() != 1)
49 throw Exception("Function " + getName() + " needs exactly one argument; passed "
50 + toString(arguments.size()) + ".", ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);
51
52 const auto & type = arguments[0].type;
53
54 if (!WhichDataType(type.get()).isUInt64())
55 throw Exception("The only argument for function " + getName() + " must be UInt64. Found "
56 + type->getName() + " instead.", ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
57
58 return std::make_shared<DataTypeString>();
59 }
60
61 bool useDefaultImplementationForConstants() const override
62 {
63 return true;
64 }
65
66 void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result, size_t input_rows_count) override
67 {
68 const SymbolIndex & symbol_index = SymbolIndex::instance();
69
70 const ColumnPtr & column = block.getByPosition(arguments[0]).column;
71 const ColumnUInt64 * column_concrete = checkAndGetColumn<ColumnUInt64>(column.get());
72
73 if (!column_concrete)
74 throw Exception("Illegal column " + column->getName() + " of argument of function " + getName(), ErrorCodes::ILLEGAL_COLUMN);
75
76 const typename ColumnVector<UInt64>::Container & data = column_concrete->getData();
77 auto result_column = ColumnString::create();
78
79 for (size_t i = 0; i < input_rows_count; ++i)
80 {
81 if (const auto * symbol = symbol_index.findSymbol(reinterpret_cast<const void *>(data[i])))
82 result_column->insertDataWithTerminatingZero(symbol->name, strlen(symbol->name) + 1);
83 else
84 result_column->insertDefault();
85 }
86
87 block.getByPosition(result).column = std::move(result_column);
88 }
89};
90
91void registerFunctionAddressToSymbol(FunctionFactory & factory)
92{
93 factory.registerFunction<FunctionAddressToSymbol>();
94}
95
96}
97
98#endif
99