be/src/exprs/function/function_helpers.cpp
Line | Count | Source |
1 | | // Licensed to the Apache Software Foundation (ASF) under one |
2 | | // or more contributor license agreements. See the NOTICE file |
3 | | // distributed with this work for additional information |
4 | | // regarding copyright ownership. The ASF licenses this file |
5 | | // to you under the Apache License, Version 2.0 (the |
6 | | // "License"); you may not use this file except in compliance |
7 | | // with the License. You may obtain a copy of the License at |
8 | | // |
9 | | // http://www.apache.org/licenses/LICENSE-2.0 |
10 | | // |
11 | | // Unless required by applicable law or agreed to in writing, |
12 | | // software distributed under the License is distributed on an |
13 | | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
14 | | // KIND, either express or implied. See the License for the |
15 | | // specific language governing permissions and limitations |
16 | | // under the License. |
17 | | // This file is copied from |
18 | | // https://github.com/ClickHouse/ClickHouse/blob/master/src/Functions/FunctionHelpers.cpp |
19 | | // and modified by Doris |
20 | | |
21 | | #include "exprs/function/function_helpers.h" |
22 | | |
23 | | #include <fmt/format.h> |
24 | | #include <glog/logging.h> |
25 | | |
26 | | #include <algorithm> |
27 | | #include <memory> |
28 | | #include <ostream> |
29 | | #include <string> |
30 | | #include <vector> |
31 | | |
32 | | #include "common/consts.h" |
33 | | #include "common/status.h" |
34 | | #include "core/block/column_with_type_and_name.h" |
35 | | #include "core/column/column_nullable.h" |
36 | | #include "core/column/column_string.h" |
37 | | #include "core/data_type/data_type_nullable.h" |
38 | | #include "exprs/function/function.h" |
39 | | #include "util/string_util.h" |
40 | | |
41 | | namespace doris { |
42 | | #include "common/compile_check_begin.h" |
43 | | std::tuple<Block, ColumnNumbers> create_block_with_nested_columns(const Block& block, |
44 | | const ColumnNumbers& args, |
45 | 46.4k | const bool need_check_same) { |
46 | 46.4k | Block res; |
47 | 46.4k | ColumnNumbers res_args(args.size()); |
48 | 46.4k | res.reserve(args.size() + 1); |
49 | | |
50 | | // only build temp block by args column, if args[i] == args[j] |
51 | | // just keep one |
52 | 154k | for (size_t i = 0; i < args.size(); ++i) { |
53 | 108k | bool is_in_res = false; |
54 | 108k | size_t pre_loc = 0; |
55 | | |
56 | 108k | if (need_check_same) { |
57 | 24 | for (int j = 0; j < i; ++j) { |
58 | 10 | if (args[j] == args[i]) { |
59 | 0 | is_in_res = true; |
60 | 0 | pre_loc = res_args[j]; |
61 | 0 | break; |
62 | 0 | } |
63 | 10 | } |
64 | 14 | } |
65 | | |
66 | 108k | if (!is_in_res) { |
67 | 108k | const auto& col = block.get_by_position(args[i]); |
68 | 108k | if (col.type->is_nullable()) { |
69 | 77.6k | const DataTypePtr& nested_type = |
70 | 77.6k | static_cast<const DataTypeNullable&>(*col.type).get_nested_type(); |
71 | | |
72 | 77.6k | if (!col.column) { |
73 | 38.8k | res.insert({nullptr, nested_type, col.name}); |
74 | 38.8k | } else if (const auto* nullable = |
75 | 38.7k | check_and_get_column<ColumnNullable>(*col.column)) { |
76 | 15.3k | const auto& nested_col = nullable->get_nested_column_ptr(); |
77 | 15.3k | res.insert({nested_col, nested_type, col.name}); |
78 | 23.4k | } else if (const auto* const_column = |
79 | 23.4k | check_and_get_column<ColumnConst>(*col.column)) { |
80 | 23.4k | const auto& nested_col = |
81 | 23.4k | check_and_get_column<ColumnNullable>(const_column->get_data_column()) |
82 | 23.4k | ->get_nested_column_ptr(); |
83 | 23.4k | res.insert({ColumnConst::create(nested_col, col.column->size()), nested_type, |
84 | 23.4k | col.name}); |
85 | 23.4k | } else { |
86 | 0 | throw doris::Exception( |
87 | 0 | ErrorCode::INTERNAL_ERROR, |
88 | 0 | "Illegal column= {}, for DataTypeNullable" + col.column->get_name()); |
89 | 0 | } |
90 | 77.6k | } else { |
91 | 30.6k | res.insert(col); |
92 | 30.6k | } |
93 | | |
94 | 108k | res_args[i] = res.columns() - 1; |
95 | 108k | } else { |
96 | 10 | res_args[i] = (int)pre_loc; |
97 | 10 | } |
98 | 108k | } |
99 | | |
100 | 46.4k | return {std::move(res), std::move(res_args)}; |
101 | 46.4k | } |
102 | | |
103 | | std::tuple<Block, ColumnNumbers, size_t> create_block_with_nested_columns(const Block& block, |
104 | | const ColumnNumbers& args, |
105 | 6 | uint32_t result) { |
106 | 6 | auto [res, res_args] = create_block_with_nested_columns(block, args, true); |
107 | | // insert result column in temp block |
108 | 6 | res.insert(block.get_by_position(result)); |
109 | 6 | return {std::move(res), std::move(res_args), res.columns() - 1}; |
110 | 6 | } |
111 | | |
112 | | void validate_argument_type(const IFunction& func, const DataTypes& arguments, |
113 | | size_t argument_index, bool (*validator_func)(const IDataType&), |
114 | 0 | const char* expected_type_description) { |
115 | 0 | if (arguments.size() <= argument_index) { |
116 | 0 | throw doris::Exception(ErrorCode::INVALID_ARGUMENT, |
117 | 0 | "Incorrect number of arguments of function {}" + func.get_name()); |
118 | 0 | } |
119 | | |
120 | 0 | const auto& argument = arguments[argument_index]; |
121 | 0 | if (!validator_func(*argument)) { |
122 | 0 | throw doris::Exception(ErrorCode::INVALID_ARGUMENT, |
123 | 0 | "Illegal type {} of {} argument of function {} expected {}", |
124 | 0 | argument->get_name(), argument_index, func.get_name(), |
125 | 0 | expected_type_description); |
126 | 0 | } |
127 | 0 | } |
128 | | |
129 | 22.2k | const ColumnConst* check_and_get_column_const_string_or_fixedstring(const IColumn* column) { |
130 | 22.2k | if (!is_column_const(*column)) return {}; |
131 | | |
132 | 11.1k | const ColumnConst* res = assert_cast<const ColumnConst*, TypeCheckOnRelease::DISABLE>(column); |
133 | | |
134 | 11.1k | if (is_column<ColumnString>(&res->get_data_column())) return res; |
135 | | |
136 | 18.4E | return {}; |
137 | 11.1k | } |
138 | | #include "common/compile_check_end.h" |
139 | | } // namespace doris |