1#include <Core/UUID.h>
2#include <IO/ReadBuffer.h>
3#include <IO/WriteBuffer.h>
4#include <IO/ReadHelpers.h>
5#include <IO/WriteHelpers.h>
6#include <IO/ReadBufferFromString.h>
7#include <IO/WriteBufferFromString.h>
8#include <IO/Operators.h>
9#include <Common/FieldVisitors.h>
10#include <Common/SipHash.h>
11
12
13namespace DB
14{
15
16template <typename T>
17static inline String formatQuoted(T x)
18{
19 WriteBufferFromOwnString wb;
20 writeQuoted(x, wb);
21 return wb.str();
22}
23
24template <typename T>
25static inline String formatQuotedWithPrefix(T x, const char * prefix)
26{
27 WriteBufferFromOwnString wb;
28 wb.write(prefix, strlen(prefix));
29 writeQuoted(x, wb);
30 return wb.str();
31}
32
33template <typename T>
34static inline void writeQuoted(const DecimalField<T> & x, WriteBuffer & buf)
35{
36 writeChar('\'', buf);
37 writeText(x.getValue(), x.getScale(), buf);
38 writeChar('\'', buf);
39}
40
41
42String FieldVisitorDump::operator() (const Null &) const { return "NULL"; }
43String FieldVisitorDump::operator() (const UInt64 & x) const { return formatQuotedWithPrefix(x, "UInt64_"); }
44String FieldVisitorDump::operator() (const Int64 & x) const { return formatQuotedWithPrefix(x, "Int64_"); }
45String FieldVisitorDump::operator() (const Float64 & x) const { return formatQuotedWithPrefix(x, "Float64_"); }
46String FieldVisitorDump::operator() (const DecimalField<Decimal32> & x) const { return formatQuotedWithPrefix(x, "Decimal32_"); }
47String FieldVisitorDump::operator() (const DecimalField<Decimal64> & x) const { return formatQuotedWithPrefix(x, "Decimal64_"); }
48String FieldVisitorDump::operator() (const DecimalField<Decimal128> & x) const { return formatQuotedWithPrefix(x, "Decimal128_"); }
49String FieldVisitorDump::operator() (const UInt128 & x) const { return formatQuotedWithPrefix(UUID(x), "UUID_"); }
50
51
52String FieldVisitorDump::operator() (const String & x) const
53{
54 WriteBufferFromOwnString wb;
55 writeQuoted(x, wb);
56 return wb.str();
57}
58
59String FieldVisitorDump::operator() (const Array & x) const
60{
61 WriteBufferFromOwnString wb;
62
63 wb << "Array_[";
64 for (auto it = x.begin(); it != x.end(); ++it)
65 {
66 if (it != x.begin())
67 wb << ", ";
68 wb << applyVisitor(*this, *it);
69 }
70 wb << ']';
71
72 return wb.str();
73}
74
75String FieldVisitorDump::operator() (const Tuple & x) const
76{
77 WriteBufferFromOwnString wb;
78
79 wb << "Tuple_(";
80 for (auto it = x.begin(); it != x.end(); ++it)
81 {
82 if (it != x.begin())
83 wb << ", ";
84 wb << applyVisitor(*this, *it);
85 }
86 wb << ')';
87
88 return wb.str();
89}
90
91String FieldVisitorDump::operator() (const AggregateFunctionStateData & x) const
92{
93 WriteBufferFromOwnString wb;
94 writeQuoted(x.name, wb);
95 writeQuoted(x.data, wb);
96 return wb.str();
97}
98
99/** In contrast to writeFloatText (and writeQuoted),
100 * even if number looks like integer after formatting, prints decimal point nevertheless (for example, Float64(1) is printed as 1.).
101 * - because resulting text must be able to be parsed back as Float64 by query parser (otherwise it will be parsed as integer).
102 *
103 * Trailing zeros after decimal point are omitted.
104 *
105 * NOTE: Roundtrip may lead to loss of precision.
106 */
107static String formatFloat(const Float64 x)
108{
109 DoubleConverter<true>::BufferType buffer;
110 double_conversion::StringBuilder builder{buffer, sizeof(buffer)};
111
112 const auto result = DoubleConverter<true>::instance().ToShortest(x, &builder);
113
114 if (!result)
115 throw Exception("Cannot print float or double number", ErrorCodes::CANNOT_PRINT_FLOAT_OR_DOUBLE_NUMBER);
116
117 return { buffer, buffer + builder.position() };
118}
119
120
121String FieldVisitorToString::operator() (const Null &) const { return "NULL"; }
122String FieldVisitorToString::operator() (const UInt64 & x) const { return formatQuoted(x); }
123String FieldVisitorToString::operator() (const Int64 & x) const { return formatQuoted(x); }
124String FieldVisitorToString::operator() (const Float64 & x) const { return formatFloat(x); }
125String FieldVisitorToString::operator() (const String & x) const { return formatQuoted(x); }
126String FieldVisitorToString::operator() (const DecimalField<Decimal32> & x) const { return formatQuoted(x); }
127String FieldVisitorToString::operator() (const DecimalField<Decimal64> & x) const { return formatQuoted(x); }
128String FieldVisitorToString::operator() (const DecimalField<Decimal128> & x) const { return formatQuoted(x); }
129String FieldVisitorToString::operator() (const UInt128 & x) const { return formatQuoted(UUID(x)); }
130String FieldVisitorToString::operator() (const AggregateFunctionStateData & x) const
131{
132 return formatQuoted(x.data);
133}
134
135String FieldVisitorToString::operator() (const Array & x) const
136{
137 WriteBufferFromOwnString wb;
138
139 wb << '[';
140 for (Array::const_iterator it = x.begin(); it != x.end(); ++it)
141 {
142 if (it != x.begin())
143 wb.write(", ", 2);
144 wb << applyVisitor(*this, *it);
145 }
146 wb << ']';
147
148 return wb.str();
149}
150
151String FieldVisitorToString::operator() (const Tuple & x) const
152{
153 WriteBufferFromOwnString wb;
154
155 wb << '(';
156 for (auto it = x.begin(); it != x.end(); ++it)
157 {
158 if (it != x.begin())
159 wb << ", ";
160 wb << applyVisitor(*this, *it);
161 }
162 wb << ')';
163
164 return wb.str();
165}
166
167
168FieldVisitorHash::FieldVisitorHash(SipHash & hash_) : hash(hash_) {}
169
170void FieldVisitorHash::operator() (const Null &) const
171{
172 UInt8 type = Field::Types::Null;
173 hash.update(type);
174}
175
176void FieldVisitorHash::operator() (const UInt64 & x) const
177{
178 UInt8 type = Field::Types::UInt64;
179 hash.update(type);
180 hash.update(x);
181}
182
183void FieldVisitorHash::operator() (const UInt128 & x) const
184{
185 UInt8 type = Field::Types::UInt128;
186 hash.update(type);
187 hash.update(x);
188}
189
190void FieldVisitorHash::operator() (const Int64 & x) const
191{
192 UInt8 type = Field::Types::Int64;
193 hash.update(type);
194 hash.update(x);
195}
196
197void FieldVisitorHash::operator() (const Float64 & x) const
198{
199 UInt8 type = Field::Types::Float64;
200 hash.update(type);
201 hash.update(x);
202}
203
204void FieldVisitorHash::operator() (const String & x) const
205{
206 UInt8 type = Field::Types::String;
207 hash.update(type);
208 hash.update(x.size());
209 hash.update(x.data(), x.size());
210}
211
212void FieldVisitorHash::operator() (const Tuple & x) const
213{
214 UInt8 type = Field::Types::Tuple;
215 hash.update(type);
216 hash.update(x.size());
217
218 for (const auto & elem : x)
219 applyVisitor(*this, elem);
220}
221
222void FieldVisitorHash::operator() (const Array & x) const
223{
224 UInt8 type = Field::Types::Array;
225 hash.update(type);
226 hash.update(x.size());
227
228 for (const auto & elem : x)
229 applyVisitor(*this, elem);
230}
231
232void FieldVisitorHash::operator() (const DecimalField<Decimal32> & x) const
233{
234 UInt8 type = Field::Types::Decimal32;
235 hash.update(type);
236 hash.update(x);
237}
238
239void FieldVisitorHash::operator() (const DecimalField<Decimal64> & x) const
240{
241 UInt8 type = Field::Types::Decimal64;
242 hash.update(type);
243 hash.update(x);
244}
245
246void FieldVisitorHash::operator() (const DecimalField<Decimal128> & x) const
247{
248 UInt8 type = Field::Types::Decimal128;
249 hash.update(type);
250 hash.update(x);
251}
252
253void FieldVisitorHash::operator() (const AggregateFunctionStateData & x) const
254{
255 UInt8 type = Field::Types::AggregateFunctionState;
256 hash.update(type);
257 hash.update(x.name.size());
258 hash.update(x.name.data(), x.name.size());
259 hash.update(x.data.size());
260 hash.update(x.data.data(), x.data.size());
261}
262
263
264}
265