1#pragma once
2
3#include <Poco/Timespan.h>
4#include <DataStreams/SizeLimits.h>
5#include <Formats/FormatSettings.h>
6#include <common/StringRef.h>
7#include <Core/Types.h>
8#include <unordered_map>
9
10
11namespace DB
12{
13
14class Field;
15struct SettingChange;
16using SettingsChanges = std::vector<SettingChange>;
17class ReadBuffer;
18class WriteBuffer;
19enum class SettingsBinaryFormat;
20
21
22/** One setting for any type.
23 * Stores a value within itself, as well as a flag - whether the value was changed.
24 * This is done so that you can send to the remote servers only changed settings (or explicitly specified in the config) values.
25 * That is, if the configuration was not specified in the config and was not dynamically changed, it is not sent to the remote server,
26 * and the remote server will use its default value.
27 */
28
29template <typename Type>
30struct SettingNumber
31{
32 Type value;
33 bool changed = false;
34
35 SettingNumber(Type x = 0) : value(x) {}
36
37 operator Type() const { return value; }
38 SettingNumber & operator= (Type x) { set(x); return *this; }
39
40 /// Serialize to a test string.
41 String toString() const;
42
43 /// Converts to a field.
44 Field toField() const;
45
46 void set(Type x);
47
48 /// Read from SQL literal.
49 void set(const Field & x);
50
51 /// Read from text string.
52 void set(const String & x);
53
54 /// Serialize to binary stream suitable for transfer over network.
55 void serialize(WriteBuffer & buf, SettingsBinaryFormat format) const;
56
57 /// Read from binary stream.
58 void deserialize(ReadBuffer & buf, SettingsBinaryFormat format);
59};
60
61using SettingUInt64 = SettingNumber<UInt64>;
62using SettingInt64 = SettingNumber<Int64>;
63using SettingFloat = SettingNumber<float>;
64using SettingBool = SettingNumber<bool>;
65
66
67/** Unlike SettingUInt64, supports the value of 'auto' - the number of processor cores without taking into account SMT.
68 * A value of 0 is also treated as auto.
69 * When serializing, `auto` is written in the same way as 0.
70 */
71struct SettingMaxThreads
72{
73 UInt64 value;
74 bool is_auto;
75 bool changed = false;
76
77 SettingMaxThreads(UInt64 x = 0) : value(x ? x : getAutoValue()), is_auto(x == 0) {}
78
79 operator UInt64() const { return value; }
80 SettingMaxThreads & operator= (UInt64 x) { set(x); return *this; }
81
82 String toString() const;
83 Field toField() const;
84
85 void set(UInt64 x);
86 void set(const Field & x);
87 void set(const String & x);
88
89 void serialize(WriteBuffer & buf, SettingsBinaryFormat format) const;
90 void deserialize(ReadBuffer & buf, SettingsBinaryFormat format);
91
92 void setAuto();
93 UInt64 getAutoValue() const;
94};
95
96
97enum class SettingTimespanIO { MILLISECOND, SECOND };
98
99template <SettingTimespanIO io_unit>
100struct SettingTimespan
101{
102 Poco::Timespan value;
103 bool changed = false;
104
105 SettingTimespan(UInt64 x = 0) : value(x * microseconds_per_io_unit) {}
106
107 operator Poco::Timespan() const { return value; }
108 SettingTimespan & operator= (const Poco::Timespan & x) { set(x); return *this; }
109
110 Poco::Timespan::TimeDiff totalSeconds() const { return value.totalSeconds(); }
111 Poco::Timespan::TimeDiff totalMilliseconds() const { return value.totalMilliseconds(); }
112
113 String toString() const;
114 Field toField() const;
115
116 void set(const Poco::Timespan & x);
117
118 void set(UInt64 x);
119 void set(const Field & x);
120 void set(const String & x);
121
122 void serialize(WriteBuffer & buf, SettingsBinaryFormat format) const;
123 void deserialize(ReadBuffer & buf, SettingsBinaryFormat format);
124
125 static constexpr UInt64 microseconds_per_io_unit = (io_unit == SettingTimespanIO::MILLISECOND) ? 1000 : 1000000;
126};
127
128using SettingSeconds = SettingTimespan<SettingTimespanIO::SECOND>;
129using SettingMilliseconds = SettingTimespan<SettingTimespanIO::MILLISECOND>;
130
131
132struct SettingString
133{
134 String value;
135 bool changed = false;
136
137 SettingString(const String & x = String{}) : value(x) {}
138
139 operator String() const { return value; }
140 SettingString & operator= (const String & x) { set(x); return *this; }
141
142 String toString() const;
143 Field toField() const;
144
145 void set(const String & x);
146 void set(const Field & x);
147
148 void serialize(WriteBuffer & buf, SettingsBinaryFormat format) const;
149 void deserialize(ReadBuffer & buf, SettingsBinaryFormat format);
150};
151
152
153struct SettingChar
154{
155public:
156 char value;
157 bool changed = false;
158
159 SettingChar(char x = '\0') : value(x) {}
160
161 operator char() const { return value; }
162 SettingChar & operator= (char x) { set(x); return *this; }
163
164 String toString() const;
165 Field toField() const;
166
167 void set(char x);
168 void set(const String & x);
169 void set(const Field & x);
170
171 void serialize(WriteBuffer & buf, SettingsBinaryFormat format) const;
172 void deserialize(ReadBuffer & buf, SettingsBinaryFormat format);
173};
174
175
176/// Template class to define enum-based settings.
177template <typename EnumType, typename Tag = void>
178struct SettingEnum
179{
180 EnumType value;
181 bool changed = false;
182
183 SettingEnum(EnumType x) : value(x) {}
184
185 operator EnumType() const { return value; }
186 SettingEnum & operator= (EnumType x) { set(x); return *this; }
187
188 String toString() const;
189 Field toField() const;
190
191 void set(EnumType x) { value = x; changed = true; }
192 void set(const Field & x);
193 void set(const String & x);
194
195 void serialize(WriteBuffer & buf, SettingsBinaryFormat format) const;
196 void deserialize(ReadBuffer & buf, SettingsBinaryFormat format);
197};
198
199
200enum class LoadBalancing
201{
202 /// among replicas with a minimum number of errors selected randomly
203 RANDOM = 0,
204 /// a replica is selected among the replicas with the minimum number of errors
205 /// with the minimum number of distinguished characters in the replica name and local hostname
206 NEAREST_HOSTNAME,
207 /// replicas are walked through strictly in order; the number of errors does not matter
208 IN_ORDER,
209 /// if first replica one has higher number of errors,
210 /// pick a random one from replicas with minimum number of errors
211 FIRST_OR_RANDOM,
212};
213using SettingLoadBalancing = SettingEnum<LoadBalancing>;
214
215
216enum class JoinStrictness
217{
218 Unspecified = 0, /// Query JOIN without strictness will throw Exception.
219 ALL, /// Query JOIN without strictness -> ALL JOIN ...
220 ANY, /// Query JOIN without strictness -> ANY JOIN ...
221};
222using SettingJoinStrictness = SettingEnum<JoinStrictness>;
223
224
225/// Which rows should be included in TOTALS.
226enum class TotalsMode
227{
228 BEFORE_HAVING = 0, /// Count HAVING for all read rows;
229 /// including those not in max_rows_to_group_by
230 /// and have not passed HAVING after grouping.
231 AFTER_HAVING_INCLUSIVE = 1, /// Count on all rows except those that have not passed HAVING;
232 /// that is, to include in TOTALS all the rows that did not pass max_rows_to_group_by.
233 AFTER_HAVING_EXCLUSIVE = 2, /// Include only the rows that passed and max_rows_to_group_by, and HAVING.
234 AFTER_HAVING_AUTO = 3, /// Automatically select between INCLUSIVE and EXCLUSIVE,
235};
236using SettingTotalsMode = SettingEnum<TotalsMode>;
237
238
239/// The settings keeps OverflowMode which cannot be OverflowMode::ANY.
240using SettingOverflowMode = SettingEnum<OverflowMode>;
241struct SettingOverflowModeGroupByTag;
242
243/// The settings keeps OverflowMode which can be OverflowMode::ANY.
244using SettingOverflowModeGroupBy = SettingEnum<OverflowMode, SettingOverflowModeGroupByTag>;
245
246
247/// The setting for executing distributed subqueries inside IN or JOIN sections.
248enum class DistributedProductMode
249{
250 DENY = 0, /// Disable
251 LOCAL, /// Convert to local query
252 GLOBAL, /// Convert to global query
253 ALLOW /// Enable
254};
255using SettingDistributedProductMode = SettingEnum<DistributedProductMode>;
256
257
258using SettingDateTimeInputFormat = SettingEnum<FormatSettings::DateTimeInputFormat>;
259
260
261enum class LogsLevel
262{
263 none = 0, /// Disable
264 error,
265 warning,
266 information,
267 debug,
268 trace,
269};
270using SettingLogsLevel = SettingEnum<LogsLevel>;
271
272
273enum class SettingsBinaryFormat
274{
275 OLD, /// Part of the settings are serialized as strings, and other part as varints. This is the old behaviour.
276 STRINGS, /// All settings are serialized as strings. Before each value the flag `is_ignorable` is serialized.
277 DEFAULT = STRINGS,
278};
279
280
281/** Template class to define collections of settings.
282 * Example of usage:
283 *
284 * mysettings.h:
285 * struct MySettings : public SettingsCollection<MySettings>
286 * {
287 * # define APPLY_FOR_MYSETTINGS(M) \
288 * M(SettingUInt64, a, 100, "Description of a", 0) \
289 * M(SettingFloat, f, 3.11, "Description of f", IMPORTANT) // IMPORTANT - means the setting can't be ignored by older versions) \
290 * M(SettingString, s, "default", "Description of s", 0)
291 *
292 * DECLARE_SETTINGS_COLLECTION(MySettings, APPLY_FOR_MYSETTINGS)
293 * };
294 *
295 * mysettings.cpp:
296 * IMPLEMENT_SETTINGS_COLLECTION(MySettings, APPLY_FOR_MYSETTINGS)
297 */
298template <class Derived>
299class SettingsCollection
300{
301private:
302 Derived & castToDerived() { return *static_cast<Derived *>(this); }
303 const Derived & castToDerived() const { return *static_cast<const Derived *>(this); }
304
305 struct MemberInfo
306 {
307 using IsChangedFunction = bool (*)(const Derived &);
308 using GetStringFunction = String (*)(const Derived &);
309 using GetFieldFunction = Field (*)(const Derived &);
310 using SetStringFunction = void (*)(Derived &, const String &);
311 using SetFieldFunction = void (*)(Derived &, const Field &);
312 using SerializeFunction = void (*)(const Derived &, WriteBuffer & buf, SettingsBinaryFormat);
313 using DeserializeFunction = void (*)(Derived &, ReadBuffer & buf, SettingsBinaryFormat);
314 using ValueToStringFunction = String (*)(const Field &);
315 using ValueToCorrespondingTypeFunction = Field (*)(const Field &);
316
317 StringRef name;
318 StringRef description;
319 bool is_important;
320 IsChangedFunction is_changed;
321 GetStringFunction get_string;
322 GetFieldFunction get_field;
323 SetStringFunction set_string;
324 SetFieldFunction set_field;
325 SerializeFunction serialize;
326 DeserializeFunction deserialize;
327 ValueToStringFunction value_to_string;
328 ValueToCorrespondingTypeFunction value_to_corresponding_type;
329 };
330
331 class MemberInfos
332 {
333 public:
334 MemberInfos();
335
336 size_t size() const { return infos.size(); }
337 const MemberInfo * data() const { return infos.data(); }
338 const MemberInfo & operator[](size_t index) const { return infos[index]; }
339
340 const MemberInfo * find(const StringRef & name) const;
341 const MemberInfo & findStrict(const StringRef & name) const;
342 size_t findIndex(const StringRef & name) const;
343 size_t findIndexStrict(const StringRef & name) const;
344
345 private:
346 void add(MemberInfo && member);
347
348 std::vector<MemberInfo> infos;
349 std::unordered_map<StringRef, size_t> by_name_map;
350 };
351
352 static const MemberInfos & members();
353
354public:
355 class const_iterator;
356
357 /// Provides read-only access to a setting.
358 class const_reference
359 {
360 public:
361 const_reference(const Derived & collection_, const MemberInfo & member_) : collection(&collection_), member(&member_) {}
362 const_reference(const const_reference & src) = default;
363 const StringRef & getName() const { return member->name; }
364 const StringRef & getDescription() const { return member->description; }
365 bool isChanged() const { return member->is_changed(*collection); }
366 Field getValue() const;
367 String getValueAsString() const { return member->get_string(*collection); }
368
369 protected:
370 friend class SettingsCollection<Derived>::const_iterator;
371 const_reference() : collection(nullptr), member(nullptr) {}
372 const_reference & operator=(const const_reference &) = default;
373 const Derived * collection;
374 const MemberInfo * member;
375 };
376
377 /// Provides access to a setting.
378 class reference : public const_reference
379 {
380 public:
381 reference(Derived & collection_, const MemberInfo & member_) : const_reference(collection_, member_) {}
382 reference(const const_reference & src) : const_reference(src) {}
383 void setValue(const Field & value) { this->member->set_field(*const_cast<Derived *>(this->collection), value); }
384 void setValue(const String & value) { this->member->set_string(*const_cast<Derived *>(this->collection), value); }
385 };
386
387 /// Iterator to iterating through all the settings.
388 class const_iterator
389 {
390 public:
391 const_iterator(const Derived & collection_, const MemberInfo * member_) : ref(const_cast<Derived &>(collection_), *member_) {}
392 const_iterator() = default;
393 const_iterator(const const_iterator & src) = default;
394 const_iterator & operator =(const const_iterator & src) = default;
395 const const_reference & operator *() const { return ref; }
396 const const_reference * operator ->() const { return &ref; }
397 const_iterator & operator ++() { ++ref.member; return *this; }
398 const_iterator operator ++(int) { const_iterator tmp = *this; ++*this; return tmp; }
399 bool operator ==(const const_iterator & rhs) const { return ref.member == rhs.ref.member && ref.collection == rhs.ref.collection; }
400 bool operator !=(const const_iterator & rhs) const { return !(*this == rhs); }
401 protected:
402 mutable reference ref;
403 };
404
405 class iterator : public const_iterator
406 {
407 public:
408 iterator(Derived & collection_, const MemberInfo * member_) : const_iterator(collection_, member_) {}
409 iterator() = default;
410 iterator(const const_iterator & src) : const_iterator(src) {}
411 iterator & operator =(const const_iterator & src) { const_iterator::operator =(src); return *this; }
412 reference & operator *() const { return this->ref; }
413 reference * operator ->() const { return &this->ref; }
414 iterator & operator ++() { const_iterator::operator ++(); return *this; }
415 iterator operator ++(int) { iterator tmp = *this; ++*this; return tmp; }
416 };
417
418 /// Returns the number of settings.
419 static size_t size() { return members().size(); }
420
421 /// Returns name of a setting by its index (0..size()-1).
422 static StringRef getName(size_t index) { return members()[index].name; }
423
424 /// Returns description of a setting.
425 static StringRef getDescription(size_t index) { return members()[index].description; }
426 static StringRef getDescription(const String & name) { return members().findStrict(name).description; }
427
428 /// Searches a setting by its name; returns `npos` if not found.
429 static size_t findIndex(const StringRef & name) { return members().findIndex(name); }
430 static constexpr size_t npos = static_cast<size_t>(-1);
431
432 /// Searches a setting by its name; throws an exception if not found.
433 static size_t findIndexStrict(const StringRef & name) { return members().findIndexStrict(name); }
434
435 /// Casts a value to a string according to a specified setting without actual changing this settings.
436 static String valueToString(size_t index, const Field & value) { return members()[index].value_to_string(value); }
437 static String valueToString(const StringRef & name, const Field & value) { return members().findStrict(name).value_to_string(value); }
438
439 /// Casts a value to a type according to a specified setting without actual changing this settings.
440 /// E.g. for SettingInt64 it casts Field to Field::Types::Int64.
441 static Field valueToCorrespondingType(size_t index, const Field & value);
442 static Field valueToCorrespondingType(const StringRef & name, const Field & value);
443
444 iterator begin() { return iterator(castToDerived(), members().data()); }
445 const_iterator begin() const { return const_iterator(castToDerived(), members().data()); }
446 iterator end() { const auto & the_members = members(); return iterator(castToDerived(), the_members.data() + the_members.size()); }
447 const_iterator end() const { const auto & the_members = members(); return const_iterator(castToDerived(), the_members.data() + the_members.size()); }
448
449 /// Returns a proxy object for accessing to a setting. Throws an exception if there is not setting with such name.
450 reference operator[](size_t index) { return reference(castToDerived(), members()[index]); }
451 reference operator[](const StringRef & name) { return reference(castToDerived(), members().findStrict(name)); }
452 const_reference operator[](size_t index) const { return const_reference(castToDerived(), members()[index]); }
453 const_reference operator[](const StringRef & name) const { return const_reference(castToDerived(), members().findStrict(name)); }
454
455 /// Searches a setting by its name; returns end() if not found.
456 iterator find(const StringRef & name);
457 const_iterator find(const StringRef & name) const;
458
459 /// Searches a setting by its name; throws an exception if not found.
460 iterator findStrict(const StringRef & name);
461 const_iterator findStrict(const StringRef & name) const;
462
463 /// Sets setting's value.
464 void set(size_t index, const Field & value) { (*this)[index].setValue(value); }
465 void set(const StringRef & name, const Field & value) { (*this)[name].setValue(value); }
466
467 /// Sets setting's value. Read value in text form from string (for example, from configuration file or from URL parameter).
468 void set(size_t index, const String & value) { (*this)[index].setValue(value); }
469 void set(const StringRef & name, const String & value) { (*this)[name].setValue(value); }
470
471 /// Returns value of a setting.
472 Field get(size_t index) const;
473 Field get(const StringRef & name) const;
474
475 /// Returns value of a setting converted to string.
476 String getAsString(size_t index) const { return (*this)[index].getValueAsString(); }
477 String getAsString(const StringRef & name) const { return (*this)[name].getValueAsString(); }
478
479 /// Returns value of a setting; returns false if there is no setting with the specified name.
480 bool tryGet(const StringRef & name, Field & value) const;
481
482 /// Returns value of a setting converted to string; returns false if there is no setting with the specified name.
483 bool tryGet(const StringRef & name, String & value) const;
484
485 /// Compares two collections of settings.
486 bool operator ==(const Derived & rhs) const;
487 bool operator!=(const Derived & rhs) const { return !(*this == rhs); }
488
489 /// Gathers all changed values (e.g. for applying them later to another collection of settings).
490 SettingsChanges changes() const;
491
492 /// Applies change to concrete setting.
493 void applyChange(const SettingChange & change);
494
495 /// Applies changes to the settings.
496 void applyChanges(const SettingsChanges & changes);
497
498 void copyChangesFrom(const Derived & src);
499
500 void copyChangesTo(Derived & dest) const;
501
502 /// Writes the settings to buffer (e.g. to be sent to remote server).
503 /// Only changed settings are written. They are written as list of contiguous name-value pairs,
504 /// finished with empty name.
505 void serialize(WriteBuffer & buf, SettingsBinaryFormat format = SettingsBinaryFormat::DEFAULT) const;
506
507 /// Reads the settings from buffer.
508 void deserialize(ReadBuffer & buf, SettingsBinaryFormat format = SettingsBinaryFormat::DEFAULT);
509};
510
511
512#define DECLARE_SETTINGS_COLLECTION(LIST_OF_SETTINGS_MACRO) \
513 LIST_OF_SETTINGS_MACRO(DECLARE_SETTINGS_COLLECTION_DECLARE_VARIABLES_HELPER_)
514
515#define DECLARE_SETTINGS_COLLECTION_DECLARE_VARIABLES_HELPER_(TYPE, NAME, DEFAULT, DESCRIPTION, FLAGS) \
516 TYPE NAME {DEFAULT};
517}
518