1#include <Interpreters/ExpressionActions.h>
2#include <Columns/ColumnFunction.h>
3#include <Columns/ColumnsCommon.h>
4#include <Common/PODArray.h>
5#include <IO/WriteHelpers.h>
6#include <Functions/IFunction.h>
7
8
9namespace DB
10{
11
12namespace ErrorCodes
13{
14 extern const int LOGICAL_ERROR;
15}
16
17ColumnFunction::ColumnFunction(size_t size, FunctionBasePtr function_, const ColumnsWithTypeAndName & columns_to_capture)
18 : size_(size), function(function_)
19{
20 appendArguments(columns_to_capture);
21}
22
23MutableColumnPtr ColumnFunction::cloneResized(size_t size) const
24{
25 ColumnsWithTypeAndName capture = captured_columns;
26 for (auto & column : capture)
27 column.column = column.column->cloneResized(size);
28
29 return ColumnFunction::create(size, function, capture);
30}
31
32ColumnPtr ColumnFunction::replicate(const Offsets & offsets) const
33{
34 if (size_ != offsets.size())
35 throw Exception("Size of offsets (" + toString(offsets.size()) + ") doesn't match size of column ("
36 + toString(size_) + ")", ErrorCodes::SIZES_OF_COLUMNS_DOESNT_MATCH);
37
38 ColumnsWithTypeAndName capture = captured_columns;
39 for (auto & column : capture)
40 column.column = column.column->replicate(offsets);
41
42 size_t replicated_size = 0 == size_ ? 0 : offsets.back();
43 return ColumnFunction::create(replicated_size, function, capture);
44}
45
46ColumnPtr ColumnFunction::cut(size_t start, size_t length) const
47{
48 ColumnsWithTypeAndName capture = captured_columns;
49 for (auto & column : capture)
50 column.column = column.column->cut(start, length);
51
52 return ColumnFunction::create(length, function, capture);
53}
54
55ColumnPtr ColumnFunction::filter(const Filter & filt, ssize_t result_size_hint) const
56{
57 if (size_ != filt.size())
58 throw Exception("Size of filter (" + toString(filt.size()) + ") doesn't match size of column ("
59 + toString(size_) + ")", ErrorCodes::SIZES_OF_COLUMNS_DOESNT_MATCH);
60
61 ColumnsWithTypeAndName capture = captured_columns;
62 for (auto & column : capture)
63 column.column = column.column->filter(filt, result_size_hint);
64
65 size_t filtered_size = 0;
66 if (capture.empty())
67 filtered_size = countBytesInFilter(filt);
68 else
69 filtered_size = capture.front().column->size();
70
71 return ColumnFunction::create(filtered_size, function, capture);
72}
73
74ColumnPtr ColumnFunction::permute(const Permutation & perm, size_t limit) const
75{
76 if (limit == 0)
77 limit = size_;
78 else
79 limit = std::min(size_, limit);
80
81 if (perm.size() < limit)
82 throw Exception("Size of permutation (" + toString(perm.size()) + ") is less than required ("
83 + toString(limit) + ")", ErrorCodes::SIZES_OF_COLUMNS_DOESNT_MATCH);
84
85 ColumnsWithTypeAndName capture = captured_columns;
86 for (auto & column : capture)
87 column.column = column.column->permute(perm, limit);
88
89 return ColumnFunction::create(limit, function, capture);
90}
91
92ColumnPtr ColumnFunction::index(const IColumn & indexes, size_t limit) const
93{
94 ColumnsWithTypeAndName capture = captured_columns;
95 for (auto & column : capture)
96 column.column = column.column->index(indexes, limit);
97
98 return ColumnFunction::create(limit, function, capture);
99}
100
101std::vector<MutableColumnPtr> ColumnFunction::scatter(IColumn::ColumnIndex num_columns,
102 const IColumn::Selector & selector) const
103{
104 if (size_ != selector.size())
105 throw Exception("Size of selector (" + toString(selector.size()) + ") doesn't match size of column ("
106 + toString(size_) + ")", ErrorCodes::SIZES_OF_COLUMNS_DOESNT_MATCH);
107
108 std::vector<size_t> counts;
109 if (captured_columns.empty())
110 counts = countColumnsSizeInSelector(num_columns, selector);
111
112 std::vector<ColumnsWithTypeAndName> captures(num_columns, captured_columns);
113
114 for (size_t capture = 0; capture < captured_columns.size(); ++capture)
115 {
116 auto parts = captured_columns[capture].column->scatter(num_columns, selector);
117 for (IColumn::ColumnIndex part = 0; part < num_columns; ++part)
118 captures[part][capture].column = std::move(parts[part]);
119 }
120
121 std::vector<MutableColumnPtr> columns;
122 columns.reserve(num_columns);
123 for (IColumn::ColumnIndex part = 0; part < num_columns; ++part)
124 {
125 auto & capture = captures[part];
126 size_t size__ = capture.empty() ? counts[part] : capture.front().column->size();
127 columns.emplace_back(ColumnFunction::create(size__, function, std::move(capture)));
128 }
129
130 return columns;
131}
132
133size_t ColumnFunction::byteSize() const
134{
135 size_t total_size = 0;
136 for (auto & column : captured_columns)
137 total_size += column.column->byteSize();
138
139 return total_size;
140}
141
142size_t ColumnFunction::allocatedBytes() const
143{
144 size_t total_size = 0;
145 for (auto & column : captured_columns)
146 total_size += column.column->allocatedBytes();
147
148 return total_size;
149}
150
151void ColumnFunction::appendArguments(const ColumnsWithTypeAndName & columns)
152{
153 auto args = function->getArgumentTypes().size();
154 auto were_captured = captured_columns.size();
155 auto wanna_capture = columns.size();
156
157 if (were_captured + wanna_capture > args)
158 throw Exception("Cannot capture " + toString(wanna_capture) + " columns because function " + function->getName()
159 + " has " + toString(args) + " arguments" +
160 (were_captured ? " and " + toString(were_captured) + " columns have already been captured" : "")
161 + ".", ErrorCodes::LOGICAL_ERROR);
162
163 for (const auto & column : columns)
164 appendArgument(column);
165}
166
167void ColumnFunction::appendArgument(const ColumnWithTypeAndName & column)
168{
169 const auto & argumnet_types = function->getArgumentTypes();
170
171 auto index = captured_columns.size();
172 if (!column.type->equals(*argumnet_types[index]))
173 throw Exception("Cannot capture column " + std::to_string(argumnet_types.size()) +
174 " because it has incompatible type: got " + column.type->getName() +
175 ", but " + argumnet_types[index]->getName() + " is expected.", ErrorCodes::LOGICAL_ERROR);
176
177 captured_columns.push_back(column);
178}
179
180ColumnWithTypeAndName ColumnFunction::reduce() const
181{
182 auto args = function->getArgumentTypes().size();
183 auto captured = captured_columns.size();
184
185 if (args != captured)
186 throw Exception("Cannot call function " + function->getName() + " because is has " + toString(args) +
187 "arguments but " + toString(captured) + " columns were captured.", ErrorCodes::LOGICAL_ERROR);
188
189 Block block(captured_columns);
190 block.insert({nullptr, function->getReturnType(), ""});
191
192 ColumnNumbers arguments(captured_columns.size());
193 for (size_t i = 0; i < captured_columns.size(); ++i)
194 arguments[i] = i;
195
196 function->execute(block, arguments, captured_columns.size(), size_);
197
198 return block.getByPosition(captured_columns.size());
199}
200
201}
202