1#include <type_traits>
2#include <DataTypes/DataTypeNumberBase.h>
3#include <Columns/ColumnVector.h>
4#include <Columns/ColumnConst.h>
5#include <IO/ReadHelpers.h>
6#include <IO/WriteHelpers.h>
7#include <Common/NaNUtils.h>
8#include <Common/typeid_cast.h>
9#include <Common/assert_cast.h>
10#include <Formats/FormatSettings.h>
11#include <Formats/ProtobufReader.h>
12#include <Formats/ProtobufWriter.h>
13
14
15namespace DB
16{
17
18template <typename T>
19void DataTypeNumberBase<T>::serializeText(const IColumn & column, size_t row_num, WriteBuffer & ostr, const FormatSettings &) const
20{
21 writeText(assert_cast<const ColumnVector<T> &>(column).getData()[row_num], ostr);
22}
23
24template <typename T>
25void DataTypeNumberBase<T>::deserializeText(IColumn & column, ReadBuffer & istr, const FormatSettings &) const
26{
27 T x;
28
29 if constexpr (is_integral_v<T> && is_arithmetic_v<T>)
30 readIntTextUnsafe(x, istr);
31 else
32 readText(x, istr);
33
34 assert_cast<ColumnVector<T> &>(column).getData().push_back(x);
35}
36
37template <typename T>
38static inline void writeDenormalNumber(T x, WriteBuffer & ostr)
39{
40 if constexpr (std::is_floating_point_v<T>)
41 {
42 if (std::signbit(x))
43 {
44 if (isNaN(x))
45 writeCString("-nan", ostr);
46 else
47 writeCString("-inf", ostr);
48 }
49 else
50 {
51 if (isNaN(x))
52 writeCString("nan", ostr);
53 else
54 writeCString("inf", ostr);
55 }
56 }
57 else
58 {
59 /// This function is not called for non floating point numbers.
60 (void)x;
61 }
62}
63
64
65template <typename T>
66void DataTypeNumberBase<T>::serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr, const FormatSettings & settings) const
67{
68 auto x = assert_cast<const ColumnVector<T> &>(column).getData()[row_num];
69 bool is_finite = isFinite(x);
70
71 const bool need_quote = (is_integral_v<T> && (sizeof(T) == 8) && settings.json.quote_64bit_integers)
72 || (settings.json.quote_denormals && !is_finite);
73
74 if (need_quote)
75 writeChar('"', ostr);
76
77 if (is_finite)
78 writeText(x, ostr);
79 else if (!settings.json.quote_denormals)
80 writeCString("null", ostr);
81 else
82 writeDenormalNumber(x, ostr);
83
84 if (need_quote)
85 writeChar('"', ostr);
86}
87
88template <typename T>
89void DataTypeNumberBase<T>::deserializeTextJSON(IColumn & column, ReadBuffer & istr, const FormatSettings &) const
90{
91 bool has_quote = false;
92 if (!istr.eof() && *istr.position() == '"') /// We understand the number both in quotes and without.
93 {
94 has_quote = true;
95 ++istr.position();
96 }
97
98 FieldType x;
99
100 /// null
101 if (!has_quote && !istr.eof() && *istr.position() == 'n')
102 {
103 ++istr.position();
104 assertString("ull", istr);
105
106 x = NaNOrZero<T>();
107 }
108 else
109 {
110 static constexpr bool is_uint8 = std::is_same_v<T, UInt8>;
111 static constexpr bool is_int8 = std::is_same_v<T, Int8>;
112
113 if (is_uint8 || is_int8)
114 {
115 // extra conditions to parse true/false strings into 1/0
116 if (istr.eof())
117 throwReadAfterEOF();
118 if (*istr.position() == 't' || *istr.position() == 'f')
119 {
120 bool tmp = false;
121 readBoolTextWord(tmp, istr);
122 x = tmp;
123 }
124 else
125 readText(x, istr);
126 }
127 else
128 {
129 readText(x, istr);
130 }
131
132 if (has_quote)
133 assertChar('"', istr);
134 }
135
136 assert_cast<ColumnVector<T> &>(column).getData().push_back(x);
137}
138
139template <typename T>
140void DataTypeNumberBase<T>::deserializeTextCSV(IColumn & column, ReadBuffer & istr, const FormatSettings &) const
141{
142 FieldType x;
143 readCSV(x, istr);
144 assert_cast<ColumnVector<T> &>(column).getData().push_back(x);
145}
146
147template <typename T>
148Field DataTypeNumberBase<T>::getDefault() const
149{
150 return NearestFieldType<FieldType>();
151}
152
153template <typename T>
154void DataTypeNumberBase<T>::serializeBinary(const Field & field, WriteBuffer & ostr) const
155{
156 /// ColumnVector<T>::ValueType is a narrower type. For example, UInt8, when the Field type is UInt64
157 typename ColumnVector<T>::ValueType x = get<NearestFieldType<FieldType>>(field);
158 writeBinary(x, ostr);
159}
160
161template <typename T>
162void DataTypeNumberBase<T>::deserializeBinary(Field & field, ReadBuffer & istr) const
163{
164 typename ColumnVector<T>::ValueType x;
165 readBinary(x, istr);
166 field = NearestFieldType<FieldType>(x);
167}
168
169template <typename T>
170void DataTypeNumberBase<T>::serializeBinary(const IColumn & column, size_t row_num, WriteBuffer & ostr) const
171{
172 writeBinary(assert_cast<const ColumnVector<T> &>(column).getData()[row_num], ostr);
173}
174
175template <typename T>
176void DataTypeNumberBase<T>::deserializeBinary(IColumn & column, ReadBuffer & istr) const
177{
178 typename ColumnVector<T>::ValueType x;
179 readBinary(x, istr);
180 assert_cast<ColumnVector<T> &>(column).getData().push_back(x);
181}
182
183template <typename T>
184void DataTypeNumberBase<T>::serializeBinaryBulk(const IColumn & column, WriteBuffer & ostr, size_t offset, size_t limit) const
185{
186 const typename ColumnVector<T>::Container & x = typeid_cast<const ColumnVector<T> &>(column).getData();
187
188 size_t size = x.size();
189
190 if (limit == 0 || offset + limit > size)
191 limit = size - offset;
192
193 if (limit)
194 ostr.write(reinterpret_cast<const char *>(&x[offset]), sizeof(typename ColumnVector<T>::ValueType) * limit);
195}
196
197template <typename T>
198void DataTypeNumberBase<T>::deserializeBinaryBulk(IColumn & column, ReadBuffer & istr, size_t limit, double /*avg_value_size_hint*/) const
199{
200 typename ColumnVector<T>::Container & x = typeid_cast<ColumnVector<T> &>(column).getData();
201 size_t initial_size = x.size();
202 x.resize(initial_size + limit);
203 size_t size = istr.readBig(reinterpret_cast<char*>(&x[initial_size]), sizeof(typename ColumnVector<T>::ValueType) * limit);
204 x.resize(initial_size + size / sizeof(typename ColumnVector<T>::ValueType));
205}
206
207
208template <typename T>
209void DataTypeNumberBase<T>::serializeProtobuf(const IColumn & column, size_t row_num, ProtobufWriter & protobuf, size_t & value_index) const
210{
211 if (value_index)
212 return;
213 value_index = static_cast<bool>(protobuf.writeNumber(assert_cast<const ColumnVector<T> &>(column).getData()[row_num]));
214}
215
216
217template <typename T>
218void DataTypeNumberBase<T>::deserializeProtobuf(IColumn & column, ProtobufReader & protobuf, bool allow_add_row, bool & row_added) const
219{
220 row_added = false;
221 T value;
222 if (!protobuf.readNumber(value))
223 return;
224
225 auto & container = typeid_cast<ColumnVector<T> &>(column).getData();
226 if (allow_add_row)
227 {
228 container.emplace_back(value);
229 row_added = true;
230 }
231 else
232 container.back() = value;
233}
234
235
236template <typename T>
237MutableColumnPtr DataTypeNumberBase<T>::createColumn() const
238{
239 return ColumnVector<T>::create();
240}
241
242template <typename T>
243bool DataTypeNumberBase<T>::isValueRepresentedByInteger() const
244{
245 return is_integral_v<T>;
246}
247
248template <typename T>
249bool DataTypeNumberBase<T>::isValueRepresentedByUnsignedInteger() const
250{
251 return is_integral_v<T> && is_unsigned_v<T>;
252}
253
254
255/// Explicit template instantiations - to avoid code bloat in headers.
256template class DataTypeNumberBase<UInt8>;
257template class DataTypeNumberBase<UInt16>;
258template class DataTypeNumberBase<UInt32>;
259template class DataTypeNumberBase<UInt64>;
260template class DataTypeNumberBase<UInt128>;
261template class DataTypeNumberBase<Int8>;
262template class DataTypeNumberBase<Int16>;
263template class DataTypeNumberBase<Int32>;
264template class DataTypeNumberBase<Int64>;
265template class DataTypeNumberBase<Float32>;
266template class DataTypeNumberBase<Float64>;
267
268}
269