aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/clickhouse/src/Functions/getServerPort.cpp
blob: faa31e5cac59c5b56091bc11e5a809dba6b6022b (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#include <DataTypes/DataTypesNumber.h>
#include <Functions/FunctionFactory.h>
#include <Functions/FunctionHelpers.h>
#include <Interpreters/Context.h>


namespace DB
{

namespace ErrorCodes
{
    extern const int NUMBER_OF_ARGUMENTS_DOESNT_MATCH;
    extern const int ILLEGAL_COLUMN;
    extern const int ILLEGAL_TYPE_OF_ARGUMENT;
}

namespace
{

class ExecutableFunctionGetServerPort : public IExecutableFunction
{
public:
    explicit ExecutableFunctionGetServerPort(UInt16 port_) : port(port_) {}

    String getName() const override { return "getServerPort"; }

    bool useDefaultImplementationForNulls() const override { return false; }

    ColumnPtr executeImpl(const ColumnsWithTypeAndName &, const DataTypePtr &, size_t input_rows_count) const override
    {
        return DataTypeNumber<UInt16>().createColumnConst(input_rows_count, port);
    }

private:
    UInt16 port;
};

class FunctionBaseGetServerPort : public IFunctionBase
{
public:
    explicit FunctionBaseGetServerPort(bool is_distributed_, UInt16 port_, DataTypes argument_types_, DataTypePtr return_type_)
        : is_distributed(is_distributed_), port(port_), argument_types(std::move(argument_types_)), return_type(std::move(return_type_))
    {
    }

    String getName() const override { return "getServerPort"; }

    const DataTypes & getArgumentTypes() const override
    {
        return argument_types;
    }

    const DataTypePtr & getResultType() const override
    {
        return return_type;
    }

    bool isDeterministic() const override { return false; }
    bool isSuitableForConstantFolding() const override { return !is_distributed; }
    bool isSuitableForShortCircuitArgumentsExecution(const DataTypesWithConstInfo & /*arguments*/) const override { return false; }

    ExecutableFunctionPtr prepare(const ColumnsWithTypeAndName &) const override
    {
        return std::make_unique<ExecutableFunctionGetServerPort>(port);
    }

private:
    bool is_distributed;
    UInt16 port;
    DataTypes argument_types;
    DataTypePtr return_type;
};

class GetServerPortOverloadResolver : public IFunctionOverloadResolver, WithContext
{
public:
    static constexpr auto name = "getServerPort";

    String getName() const override { return name; }

    static FunctionOverloadResolverPtr create(ContextPtr context_)
    {
        return std::make_unique<GetServerPortOverloadResolver>(context_);
    }

    explicit GetServerPortOverloadResolver(ContextPtr context_) : WithContext(context_) {}

    size_t getNumberOfArguments() const override { return 1; }
    ColumnNumbers getArgumentsThatAreAlwaysConstant() const override { return {0}; }
    bool isDeterministic() const override { return false; }

    DataTypePtr getReturnTypeImpl(const DataTypes & data_types) const override
    {
        size_t number_of_arguments = data_types.size();
        if (number_of_arguments != 1)
            throw Exception(
                ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH,
                "Number of arguments for function {} doesn't match: passed {}, should be 1",
                getName(),
                number_of_arguments);
        return std::make_shared<DataTypeNumber<UInt16>>();
    }

    FunctionBasePtr buildImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr & return_type) const override
    {
        if (!isString(arguments[0].type))
            throw Exception(
                ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT,
                "The argument of function {} should be a constant string with the name of a setting",
                getName());
        const auto * column = arguments[0].column.get();
        if (!column || !checkAndGetColumnConstStringOrFixedString(column))
            throw Exception(
                ErrorCodes::ILLEGAL_COLUMN,
                "The argument of function {} should be a constant string with the name of a setting",
                getName());

        String port_name{column->getDataAt(0)};
        auto port = getContext()->getServerPort(port_name);

        DataTypes argument_types;
        argument_types.emplace_back(arguments.back().type);
        return std::make_unique<FunctionBaseGetServerPort>(getContext()->isDistributed(), port, argument_types, return_type);
    }
};

}

REGISTER_FUNCTION(GetServerPort)
{
    factory.registerFunction<GetServerPortOverloadResolver>();
}

}