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 scalar value of sub queries from query context via IAST::Hash.
21 */
22class FunctionGetScalar : public IFunction
23{
24public:
25 static constexpr auto name = "__getScalar";
26 static FunctionPtr create(const Context & context)
27 {
28 return std::make_shared<FunctionGetScalar>(context);
29 }
30
31 FunctionGetScalar(const Context & context_) : context(context_) {}
32
33 String getName() const override
34 {
35 return name;
36 }
37
38 size_t getNumberOfArguments() const override
39 {
40 return 1;
41 }
42
43 DataTypePtr getReturnTypeImpl(const ColumnsWithTypeAndName & arguments) const override
44 {
45 if (arguments.size() != 1 || !isString(arguments[0].type) || !arguments[0].column || !isColumnConst(*arguments[0].column))
46 throw Exception("Function " + getName() + " accepts one const string argument", ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
47 auto scalar_name = assert_cast<const ColumnConst &>(*arguments[0].column).getField().get<String>();
48 scalar = context.getScalar(scalar_name).getByPosition(0);
49 return scalar.type;
50 }
51
52 void executeImpl(Block & block, const ColumnNumbers &, size_t result, size_t input_rows_count) override
53 {
54 block.getByPosition(result).column = ColumnConst::create(scalar.column, input_rows_count);
55 }
56
57private:
58 mutable ColumnWithTypeAndName scalar;
59 const Context & context;
60};
61
62
63void registerFunctionGetScalar(FunctionFactory & factory)
64{
65 factory.registerFunction<FunctionGetScalar>();
66}
67
68}
69