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