1#pragma once
2
3#include <Core/Field.h>
4#include <Common/Exception.h>
5#include <Columns/IColumn.h>
6#include <Common/typeid_cast.h>
7#include <Common/assert_cast.h>
8
9
10namespace DB
11{
12
13namespace ErrorCodes
14{
15 extern const int NOT_IMPLEMENTED;
16}
17
18
19/** ColumnConst contains another column with single element,
20 * but looks like a column with arbitrary amount of same elements.
21 */
22class ColumnConst final : public COWHelper<IColumn, ColumnConst>
23{
24private:
25 friend class COWHelper<IColumn, ColumnConst>;
26
27 WrappedPtr data;
28 size_t s;
29
30 ColumnConst(const ColumnPtr & data, size_t s_);
31 ColumnConst(const ColumnConst & src) = default;
32
33public:
34 ColumnPtr convertToFullColumn() const;
35
36 ColumnPtr convertToFullColumnIfConst() const override
37 {
38 return convertToFullColumn();
39 }
40
41 ColumnPtr removeLowCardinality() const;
42
43 std::string getName() const override
44 {
45 return "Const(" + data->getName() + ")";
46 }
47
48 const char * getFamilyName() const override
49 {
50 return "Const";
51 }
52
53 MutableColumnPtr cloneResized(size_t new_size) const override
54 {
55 return ColumnConst::create(data, new_size);
56 }
57
58 size_t size() const override
59 {
60 return s;
61 }
62
63 Field operator[](size_t) const override
64 {
65 return (*data)[0];
66 }
67
68 void get(size_t, Field & res) const override
69 {
70 data->get(0, res);
71 }
72
73 StringRef getDataAt(size_t) const override
74 {
75 return data->getDataAt(0);
76 }
77
78 StringRef getDataAtWithTerminatingZero(size_t) const override
79 {
80 return data->getDataAtWithTerminatingZero(0);
81 }
82
83 UInt64 get64(size_t) const override
84 {
85 return data->get64(0);
86 }
87
88 UInt64 getUInt(size_t) const override
89 {
90 return data->getUInt(0);
91 }
92
93 Int64 getInt(size_t) const override
94 {
95 return data->getInt(0);
96 }
97
98 bool getBool(size_t) const override
99 {
100 return data->getBool(0);
101 }
102
103 Float64 getFloat64(size_t) const override
104 {
105 return data->getFloat64(0);
106 }
107
108 Float32 getFloat32(size_t) const override
109 {
110 return data->getFloat32(0);
111 }
112
113 bool isNullAt(size_t) const override
114 {
115 return data->isNullAt(0);
116 }
117
118 void insertRangeFrom(const IColumn &, size_t /*start*/, size_t length) override
119 {
120 s += length;
121 }
122
123 void insert(const Field &) override
124 {
125 ++s;
126 }
127
128 void insertData(const char *, size_t) override
129 {
130 ++s;
131 }
132
133 void insertFrom(const IColumn &, size_t) override
134 {
135 ++s;
136 }
137
138 void insertDefault() override
139 {
140 ++s;
141 }
142
143 void popBack(size_t n) override
144 {
145 s -= n;
146 }
147
148 StringRef serializeValueIntoArena(size_t, Arena & arena, char const *& begin) const override
149 {
150 return data->serializeValueIntoArena(0, arena, begin);
151 }
152
153 const char * deserializeAndInsertFromArena(const char * pos) override
154 {
155 auto res = data->deserializeAndInsertFromArena(pos);
156 data->popBack(1);
157 ++s;
158 return res;
159 }
160
161 void updateHashWithValue(size_t, SipHash & hash) const override
162 {
163 data->updateHashWithValue(0, hash);
164 }
165
166 ColumnPtr filter(const Filter & filt, ssize_t result_size_hint) const override;
167 ColumnPtr replicate(const Offsets & offsets) const override;
168 ColumnPtr permute(const Permutation & perm, size_t limit) const override;
169 ColumnPtr index(const IColumn & indexes, size_t limit) const override;
170 void getPermutation(bool reverse, size_t limit, int nan_direction_hint, Permutation & res) const override;
171
172 size_t byteSize() const override
173 {
174 return data->byteSize() + sizeof(s);
175 }
176
177 size_t allocatedBytes() const override
178 {
179 return data->allocatedBytes() + sizeof(s);
180 }
181
182 int compareAt(size_t, size_t, const IColumn & rhs, int nan_direction_hint) const override
183 {
184 return data->compareAt(0, 0, *assert_cast<const ColumnConst &>(rhs).data, nan_direction_hint);
185 }
186
187 MutableColumns scatter(ColumnIndex num_columns, const Selector & selector) const override;
188
189 void gather(ColumnGathererStream &) override
190 {
191 throw Exception("Cannot gather into constant column " + getName(), ErrorCodes::NOT_IMPLEMENTED);
192 }
193
194 void getExtremes(Field & min, Field & max) const override
195 {
196 data->getExtremes(min, max);
197 }
198
199 void forEachSubcolumn(ColumnCallback callback) override
200 {
201 callback(data);
202 }
203
204 bool structureEquals(const IColumn & rhs) const override
205 {
206 if (auto rhs_concrete = typeid_cast<const ColumnConst *>(&rhs))
207 return data->structureEquals(*rhs_concrete->data);
208 return false;
209 }
210
211 bool isNullable() const override { return isColumnNullable(*data); }
212 bool onlyNull() const override { return data->isNullAt(0); }
213 bool isNumeric() const override { return data->isNumeric(); }
214 bool isFixedAndContiguous() const override { return data->isFixedAndContiguous(); }
215 bool valuesHaveFixedSize() const override { return data->valuesHaveFixedSize(); }
216 size_t sizeOfValueIfFixed() const override { return data->sizeOfValueIfFixed(); }
217 StringRef getRawData() const override { return data->getRawData(); }
218
219 /// Not part of the common interface.
220
221 IColumn & getDataColumn() { return *data; }
222 const IColumn & getDataColumn() const { return *data; }
223 const ColumnPtr & getDataColumnPtr() const { return data; }
224
225 Field getField() const { return getDataColumn()[0]; }
226
227 /// The constant value. It is valid even if the size of the column is 0.
228 template <typename T>
229 T getValue() const { return getField().safeGet<NearestFieldType<T>>(); }
230};
231
232}
233