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 | |
13 | namespace DB |
14 | { |
15 | |
16 | template <typename T> |
17 | static inline String formatQuoted(T x) |
18 | { |
19 | WriteBufferFromOwnString wb; |
20 | writeQuoted(x, wb); |
21 | return wb.str(); |
22 | } |
23 | |
24 | template <typename T> |
25 | static 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 | |
33 | template <typename T> |
34 | static 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 | |
42 | String FieldVisitorDump::operator() (const Null &) const { return "NULL" ; } |
43 | String FieldVisitorDump::operator() (const UInt64 & x) const { return formatQuotedWithPrefix(x, "UInt64_" ); } |
44 | String FieldVisitorDump::operator() (const Int64 & x) const { return formatQuotedWithPrefix(x, "Int64_" ); } |
45 | String FieldVisitorDump::operator() (const Float64 & x) const { return formatQuotedWithPrefix(x, "Float64_" ); } |
46 | String FieldVisitorDump::operator() (const DecimalField<Decimal32> & x) const { return formatQuotedWithPrefix(x, "Decimal32_" ); } |
47 | String FieldVisitorDump::operator() (const DecimalField<Decimal64> & x) const { return formatQuotedWithPrefix(x, "Decimal64_" ); } |
48 | String FieldVisitorDump::operator() (const DecimalField<Decimal128> & x) const { return formatQuotedWithPrefix(x, "Decimal128_" ); } |
49 | String FieldVisitorDump::operator() (const UInt128 & x) const { return formatQuotedWithPrefix(UUID(x), "UUID_" ); } |
50 | |
51 | |
52 | String FieldVisitorDump::operator() (const String & x) const |
53 | { |
54 | WriteBufferFromOwnString wb; |
55 | writeQuoted(x, wb); |
56 | return wb.str(); |
57 | } |
58 | |
59 | String 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 | |
75 | String 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 | |
91 | String 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 | */ |
107 | static 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 | |
121 | String FieldVisitorToString::operator() (const Null &) const { return "NULL" ; } |
122 | String FieldVisitorToString::operator() (const UInt64 & x) const { return formatQuoted(x); } |
123 | String FieldVisitorToString::operator() (const Int64 & x) const { return formatQuoted(x); } |
124 | String FieldVisitorToString::operator() (const Float64 & x) const { return formatFloat(x); } |
125 | String FieldVisitorToString::operator() (const String & x) const { return formatQuoted(x); } |
126 | String FieldVisitorToString::operator() (const DecimalField<Decimal32> & x) const { return formatQuoted(x); } |
127 | String FieldVisitorToString::operator() (const DecimalField<Decimal64> & x) const { return formatQuoted(x); } |
128 | String FieldVisitorToString::operator() (const DecimalField<Decimal128> & x) const { return formatQuoted(x); } |
129 | String FieldVisitorToString::operator() (const UInt128 & x) const { return formatQuoted(UUID(x)); } |
130 | String FieldVisitorToString::operator() (const AggregateFunctionStateData & x) const |
131 | { |
132 | return formatQuoted(x.data); |
133 | } |
134 | |
135 | String 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 | |
151 | String 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 | |
168 | FieldVisitorHash::FieldVisitorHash(SipHash & hash_) : hash(hash_) {} |
169 | |
170 | void FieldVisitorHash::operator() (const Null &) const |
171 | { |
172 | UInt8 type = Field::Types::Null; |
173 | hash.update(type); |
174 | } |
175 | |
176 | void FieldVisitorHash::operator() (const UInt64 & x) const |
177 | { |
178 | UInt8 type = Field::Types::UInt64; |
179 | hash.update(type); |
180 | hash.update(x); |
181 | } |
182 | |
183 | void FieldVisitorHash::operator() (const UInt128 & x) const |
184 | { |
185 | UInt8 type = Field::Types::UInt128; |
186 | hash.update(type); |
187 | hash.update(x); |
188 | } |
189 | |
190 | void FieldVisitorHash::operator() (const Int64 & x) const |
191 | { |
192 | UInt8 type = Field::Types::Int64; |
193 | hash.update(type); |
194 | hash.update(x); |
195 | } |
196 | |
197 | void FieldVisitorHash::operator() (const Float64 & x) const |
198 | { |
199 | UInt8 type = Field::Types::Float64; |
200 | hash.update(type); |
201 | hash.update(x); |
202 | } |
203 | |
204 | void 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 | |
212 | void 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 | |
222 | void 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 | |
232 | void FieldVisitorHash::operator() (const DecimalField<Decimal32> & x) const |
233 | { |
234 | UInt8 type = Field::Types::Decimal32; |
235 | hash.update(type); |
236 | hash.update(x); |
237 | } |
238 | |
239 | void FieldVisitorHash::operator() (const DecimalField<Decimal64> & x) const |
240 | { |
241 | UInt8 type = Field::Types::Decimal64; |
242 | hash.update(type); |
243 | hash.update(x); |
244 | } |
245 | |
246 | void FieldVisitorHash::operator() (const DecimalField<Decimal128> & x) const |
247 | { |
248 | UInt8 type = Field::Types::Decimal128; |
249 | hash.update(type); |
250 | hash.update(x); |
251 | } |
252 | |
253 | void 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 | |