1 | #include <Functions/IFunctionImpl.h> |
2 | #include <Functions/FunctionHelpers.h> |
3 | #include <DataTypes/DataTypesNumber.h> |
4 | #include <Columns/ColumnsNumber.h> |
5 | #include <ext/range.h> |
6 | |
7 | |
8 | namespace DB |
9 | { |
10 | |
11 | namespace ErrorCodes |
12 | { |
13 | extern const int ILLEGAL_COLUMN; |
14 | extern const int ILLEGAL_TYPE_OF_ARGUMENT; |
15 | } |
16 | |
17 | |
18 | template <typename Impl> |
19 | class FunctionNumericPredicate : public IFunction |
20 | { |
21 | public: |
22 | static constexpr auto name = Impl::name; |
23 | static FunctionPtr create(const Context &) |
24 | { |
25 | return std::make_shared<FunctionNumericPredicate>(); |
26 | } |
27 | |
28 | String getName() const override |
29 | { |
30 | return name; |
31 | } |
32 | |
33 | size_t getNumberOfArguments() const override |
34 | { |
35 | return 1; |
36 | } |
37 | |
38 | DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override |
39 | { |
40 | if (!isNativeNumber(arguments.front())) |
41 | throw Exception{"Argument for function " + getName() + " must be number" , ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT}; |
42 | |
43 | return std::make_shared<DataTypeUInt8>(); |
44 | } |
45 | |
46 | bool useDefaultImplementationForConstants() const override { return true; } |
47 | |
48 | void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result, size_t /*input_rows_count*/) override |
49 | { |
50 | const auto in = block.getByPosition(arguments.front()).column.get(); |
51 | |
52 | if ( !execute<UInt8>(block, in, result) |
53 | && !execute<UInt16>(block, in, result) |
54 | && !execute<UInt32>(block, in, result) |
55 | && !execute<UInt64>(block, in, result) |
56 | && !execute<Int8>(block, in, result) |
57 | && !execute<Int16>(block, in, result) |
58 | && !execute<Int32>(block, in, result) |
59 | && !execute<Int64>(block, in, result) |
60 | && !execute<Float32>(block, in, result) |
61 | && !execute<Float64>(block, in, result)) |
62 | throw Exception{"Illegal column " + in->getName() + " of first argument of function " + getName(), ErrorCodes::ILLEGAL_COLUMN}; |
63 | } |
64 | |
65 | template <typename T> |
66 | bool execute(Block & block, const IColumn * in_untyped, const size_t result) |
67 | { |
68 | if (const auto in = checkAndGetColumn<ColumnVector<T>>(in_untyped)) |
69 | { |
70 | const auto size = in->size(); |
71 | |
72 | auto out = ColumnUInt8::create(size); |
73 | |
74 | const auto & in_data = in->getData(); |
75 | auto & out_data = out->getData(); |
76 | |
77 | for (const auto i : ext::range(0, size)) |
78 | out_data[i] = Impl::execute(in_data[i]); |
79 | |
80 | block.getByPosition(result).column = std::move(out); |
81 | return true; |
82 | } |
83 | |
84 | return false; |
85 | } |
86 | }; |
87 | |
88 | } |
89 | |