mirror of https://github.com/ByConity/ByConity
Split SettingsCollection.h into 3 files: SettingsFields.h, SettingsEnums.h, SettingsCollection.h
This commit is contained in:
parent
90602b869a
commit
18e3f1f60d
|
@ -20,7 +20,6 @@
|
|||
#include <Common/ThreadStatus.h>
|
||||
#include <Common/config_version.h>
|
||||
#include <Common/quoteString.h>
|
||||
#include <Common/SettingsChanges.h>
|
||||
#include <IO/ReadBufferFromString.h>
|
||||
#include <IO/WriteBufferFromFileDescriptor.h>
|
||||
#include <IO/UseSSL.h>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <Access/MultipleAccessStorage.h>
|
||||
#include <Poco/AutoPtr.h>
|
||||
#include <Common/SettingsChanges.h>
|
||||
#include <boost/container/flat_set.hpp>
|
||||
#include <memory>
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
#include <Common/ProfileEvents.h>
|
||||
#include <Common/MemoryTracker.h>
|
||||
|
||||
#include <Core/SettingsCollection.h>
|
||||
#include <Core/SettingsEnums.h>
|
||||
|
||||
#include <IO/Progress.h>
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <Core/SettingsCollection.h>
|
||||
#include <Core/SettingsEnums.h>
|
||||
#include <Core/Defines.h>
|
||||
|
||||
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
#include <Core/SettingsCollectionImpl.h>
|
||||
|
||||
#include <Core/Field.h>
|
||||
#include <Common/getNumberOfPhysicalCPUCores.h>
|
||||
#include <Common/FieldVisitors.h>
|
||||
#include <common/logger_useful.h>
|
||||
#include <IO/ReadHelpers.h>
|
||||
|
@ -14,555 +13,10 @@ namespace DB
|
|||
{
|
||||
namespace ErrorCodes
|
||||
{
|
||||
extern const int UNKNOWN_LOAD_BALANCING;
|
||||
extern const int UNKNOWN_OVERFLOW_MODE;
|
||||
extern const int UNKNOWN_TOTALS_MODE;
|
||||
extern const int UNKNOWN_DISTRIBUTED_PRODUCT_MODE;
|
||||
extern const int UNKNOWN_JOIN;
|
||||
extern const int SIZE_OF_FIXED_STRING_DOESNT_MATCH;
|
||||
extern const int BAD_ARGUMENTS;
|
||||
extern const int UNKNOWN_SETTING;
|
||||
extern const int CANNOT_PARSE_BOOL;
|
||||
}
|
||||
|
||||
|
||||
template <typename Type>
|
||||
String SettingFieldNumber<Type>::toString() const
|
||||
{
|
||||
return DB::toString(value);
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
Field SettingFieldNumber<Type>::toField() const
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
void SettingFieldNumber<Type>::set(Type x)
|
||||
{
|
||||
value = x;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
void SettingFieldNumber<Type>::set(const Field & x)
|
||||
{
|
||||
if (x.getType() == Field::Types::String)
|
||||
set(get<const String &>(x));
|
||||
else
|
||||
set(applyVisitor(FieldVisitorConvertToNumber<Type>(), x));
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
void SettingFieldNumber<Type>::set(const String & x)
|
||||
{
|
||||
set(parseWithSizeSuffix<Type>(x));
|
||||
}
|
||||
|
||||
template <>
|
||||
void SettingFieldNumber<bool>::set(const String & x)
|
||||
{
|
||||
if (x.size() == 1)
|
||||
{
|
||||
if (x[0] == '0')
|
||||
set(false);
|
||||
else if (x[0] == '1')
|
||||
set(true);
|
||||
else
|
||||
throw Exception("Cannot parse bool from string '" + x + "'", ErrorCodes::CANNOT_PARSE_BOOL);
|
||||
}
|
||||
else
|
||||
{
|
||||
ReadBufferFromString buf(x);
|
||||
if (checkStringCaseInsensitive("true", buf))
|
||||
set(true);
|
||||
else if (checkStringCaseInsensitive("false", buf))
|
||||
set(false);
|
||||
else
|
||||
throw Exception("Cannot parse bool from string '" + x + "'", ErrorCodes::CANNOT_PARSE_BOOL);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
void SettingFieldNumber<Type>::serialize(WriteBuffer & buf, SettingsBinaryFormat format) const
|
||||
{
|
||||
if (format >= SettingsBinaryFormat::STRINGS)
|
||||
{
|
||||
writeStringBinary(toString(), buf);
|
||||
return;
|
||||
}
|
||||
|
||||
if constexpr (is_integral_v<Type> && is_unsigned_v<Type>)
|
||||
writeVarUInt(static_cast<UInt64>(value), buf);
|
||||
else if constexpr (is_integral_v<Type> && is_signed_v<Type>)
|
||||
writeVarInt(static_cast<Int64>(value), buf);
|
||||
else
|
||||
{
|
||||
static_assert(std::is_floating_point_v<Type>);
|
||||
writeStringBinary(toString(), buf);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
void SettingFieldNumber<Type>::deserialize(ReadBuffer & buf, SettingsBinaryFormat format)
|
||||
{
|
||||
if (format >= SettingsBinaryFormat::STRINGS)
|
||||
{
|
||||
String x;
|
||||
readStringBinary(x, buf);
|
||||
set(x);
|
||||
return;
|
||||
}
|
||||
|
||||
if constexpr (is_integral_v<Type> && is_unsigned_v<Type>)
|
||||
{
|
||||
UInt64 x;
|
||||
readVarUInt(x, buf);
|
||||
set(static_cast<Type>(x));
|
||||
}
|
||||
else if constexpr (is_integral_v<Type> && is_signed_v<Type>)
|
||||
{
|
||||
Int64 x;
|
||||
readVarInt(x, buf);
|
||||
set(static_cast<Type>(x));
|
||||
}
|
||||
else
|
||||
{
|
||||
static_assert(std::is_floating_point_v<Type>);
|
||||
String x;
|
||||
readStringBinary(x, buf);
|
||||
set(x);
|
||||
}
|
||||
}
|
||||
|
||||
template struct SettingFieldNumber<UInt64>;
|
||||
template struct SettingFieldNumber<Int64>;
|
||||
template struct SettingFieldNumber<float>;
|
||||
template struct SettingFieldNumber<bool>;
|
||||
|
||||
|
||||
String SettingFieldMaxThreads::toString() const
|
||||
{
|
||||
/// Instead of the `auto` value, we output the actual value to make it easier to see.
|
||||
return is_auto ? ("auto(" + DB::toString(value) + ")") : DB::toString(value);
|
||||
}
|
||||
|
||||
Field SettingFieldMaxThreads::toField() const
|
||||
{
|
||||
return is_auto ? 0 : value;
|
||||
}
|
||||
|
||||
void SettingFieldMaxThreads::set(UInt64 x)
|
||||
{
|
||||
value = x ? x : getAutoValue();
|
||||
is_auto = x == 0;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
void SettingFieldMaxThreads::set(const Field & x)
|
||||
{
|
||||
if (x.getType() == Field::Types::String)
|
||||
set(get<const String &>(x));
|
||||
else
|
||||
set(applyVisitor(FieldVisitorConvertToNumber<UInt64>(), x));
|
||||
}
|
||||
|
||||
void SettingFieldMaxThreads::set(const String & x)
|
||||
{
|
||||
if (startsWith(x, "auto"))
|
||||
setAuto();
|
||||
else
|
||||
set(parse<UInt64>(x));
|
||||
}
|
||||
|
||||
void SettingFieldMaxThreads::serialize(WriteBuffer & buf, SettingsBinaryFormat format) const
|
||||
{
|
||||
if (format >= SettingsBinaryFormat::STRINGS)
|
||||
{
|
||||
writeStringBinary(is_auto ? "auto" : DB::toString(value), buf);
|
||||
return;
|
||||
}
|
||||
|
||||
writeVarUInt(is_auto ? 0 : value, buf);
|
||||
}
|
||||
|
||||
void SettingFieldMaxThreads::deserialize(ReadBuffer & buf, SettingsBinaryFormat format)
|
||||
{
|
||||
if (format >= SettingsBinaryFormat::STRINGS)
|
||||
{
|
||||
String x;
|
||||
readStringBinary(x, buf);
|
||||
set(x);
|
||||
return;
|
||||
}
|
||||
|
||||
UInt64 x = 0;
|
||||
readVarUInt(x, buf);
|
||||
set(x);
|
||||
}
|
||||
|
||||
void SettingFieldMaxThreads::setAuto()
|
||||
{
|
||||
value = getAutoValue();
|
||||
is_auto = true;
|
||||
}
|
||||
|
||||
UInt64 SettingFieldMaxThreads::getAutoValue()
|
||||
{
|
||||
return getNumberOfPhysicalCPUCores();
|
||||
}
|
||||
|
||||
|
||||
template <SettingFieldTimespanIO io_unit>
|
||||
String SettingFieldTimespan<io_unit>::toString() const
|
||||
{
|
||||
return DB::toString(value.totalMicroseconds() / microseconds_per_io_unit);
|
||||
}
|
||||
|
||||
template <SettingFieldTimespanIO io_unit>
|
||||
Field SettingFieldTimespan<io_unit>::toField() const
|
||||
{
|
||||
return value.totalMicroseconds() / microseconds_per_io_unit;
|
||||
}
|
||||
|
||||
template <SettingFieldTimespanIO io_unit>
|
||||
void SettingFieldTimespan<io_unit>::set(const Poco::Timespan & x)
|
||||
{
|
||||
value = x;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
template <SettingFieldTimespanIO io_unit>
|
||||
void SettingFieldTimespan<io_unit>::set(UInt64 x)
|
||||
{
|
||||
set(Poco::Timespan(x * microseconds_per_io_unit));
|
||||
}
|
||||
|
||||
template <SettingFieldTimespanIO io_unit>
|
||||
void SettingFieldTimespan<io_unit>::set(const Field & x)
|
||||
{
|
||||
if (x.getType() == Field::Types::String)
|
||||
set(get<const String &>(x));
|
||||
else
|
||||
set(applyVisitor(FieldVisitorConvertToNumber<UInt64>(), x));
|
||||
}
|
||||
|
||||
template <SettingFieldTimespanIO io_unit>
|
||||
void SettingFieldTimespan<io_unit>::set(const String & x)
|
||||
{
|
||||
set(parse<UInt64>(x));
|
||||
}
|
||||
|
||||
template <SettingFieldTimespanIO io_unit>
|
||||
void SettingFieldTimespan<io_unit>::serialize(WriteBuffer & buf, SettingsBinaryFormat format) const
|
||||
{
|
||||
if (format >= SettingsBinaryFormat::STRINGS)
|
||||
{
|
||||
writeStringBinary(toString(), buf);
|
||||
return;
|
||||
}
|
||||
|
||||
writeVarUInt(value.totalMicroseconds() / microseconds_per_io_unit, buf);
|
||||
}
|
||||
|
||||
template <SettingFieldTimespanIO io_unit>
|
||||
void SettingFieldTimespan<io_unit>::deserialize(ReadBuffer & buf, SettingsBinaryFormat format)
|
||||
{
|
||||
if (format >= SettingsBinaryFormat::STRINGS)
|
||||
{
|
||||
String x;
|
||||
readStringBinary(x, buf);
|
||||
set(x);
|
||||
return;
|
||||
}
|
||||
|
||||
UInt64 x = 0;
|
||||
readVarUInt(x, buf);
|
||||
set(x);
|
||||
}
|
||||
|
||||
template struct SettingFieldTimespan<SettingFieldTimespanIO::SECOND>;
|
||||
template struct SettingFieldTimespan<SettingFieldTimespanIO::MILLISECOND>;
|
||||
|
||||
|
||||
String SettingFieldString::toString() const
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
Field SettingFieldString::toField() const
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
void SettingFieldString::set(const String & x)
|
||||
{
|
||||
value = x;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
void SettingFieldString::set(const Field & x)
|
||||
{
|
||||
set(safeGet<const String &>(x));
|
||||
}
|
||||
|
||||
void SettingFieldString::serialize(WriteBuffer & buf, SettingsBinaryFormat) const
|
||||
{
|
||||
writeStringBinary(value, buf);
|
||||
}
|
||||
|
||||
void SettingFieldString::deserialize(ReadBuffer & buf, SettingsBinaryFormat)
|
||||
{
|
||||
String s;
|
||||
readStringBinary(s, buf);
|
||||
set(s);
|
||||
}
|
||||
|
||||
|
||||
String SettingFieldChar::toString() const
|
||||
{
|
||||
return String(1, value);
|
||||
}
|
||||
|
||||
Field SettingFieldChar::toField() const
|
||||
{
|
||||
return toString();
|
||||
}
|
||||
|
||||
void SettingFieldChar::set(char x)
|
||||
{
|
||||
value = x;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
void SettingFieldChar::set(const String & x)
|
||||
{
|
||||
if (x.size() > 1)
|
||||
throw Exception("A setting's value string has to be an exactly one character long", ErrorCodes::SIZE_OF_FIXED_STRING_DOESNT_MATCH);
|
||||
char c = (x.size() == 1) ? x[0] : '\0';
|
||||
set(c);
|
||||
}
|
||||
|
||||
void SettingFieldChar::set(const Field & x)
|
||||
{
|
||||
const String & s = safeGet<const String &>(x);
|
||||
set(s);
|
||||
}
|
||||
|
||||
void SettingFieldChar::serialize(WriteBuffer & buf, SettingsBinaryFormat) const
|
||||
{
|
||||
writeStringBinary(toString(), buf);
|
||||
}
|
||||
|
||||
void SettingFieldChar::deserialize(ReadBuffer & buf, SettingsBinaryFormat)
|
||||
{
|
||||
String s;
|
||||
readStringBinary(s, buf);
|
||||
set(s);
|
||||
}
|
||||
|
||||
|
||||
template <typename EnumType, typename Tag>
|
||||
void SettingFieldEnum<EnumType, Tag>::serialize(WriteBuffer & buf, SettingsBinaryFormat) const
|
||||
{
|
||||
writeStringBinary(toString(), buf);
|
||||
}
|
||||
|
||||
template <typename EnumType, typename Tag>
|
||||
void SettingFieldEnum<EnumType, Tag>::deserialize(ReadBuffer & buf, SettingsBinaryFormat)
|
||||
{
|
||||
String s;
|
||||
readStringBinary(s, buf);
|
||||
set(s);
|
||||
}
|
||||
|
||||
template <typename EnumType, typename Tag>
|
||||
Field SettingFieldEnum<EnumType, Tag>::toField() const
|
||||
{
|
||||
return toString();
|
||||
}
|
||||
|
||||
template <typename EnumType, typename Tag>
|
||||
void SettingFieldEnum<EnumType, Tag>::set(const Field & x)
|
||||
{
|
||||
set(safeGet<const String &>(x));
|
||||
}
|
||||
|
||||
|
||||
String SettingFieldURI::toString() const
|
||||
{
|
||||
return value.toString();
|
||||
}
|
||||
|
||||
Field SettingFieldURI::toField() const
|
||||
{
|
||||
return value.toString();
|
||||
}
|
||||
|
||||
void SettingFieldURI::set(const Poco::URI & x)
|
||||
{
|
||||
value = x;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
void SettingFieldURI::set(const Field & x)
|
||||
{
|
||||
const String & s = safeGet<const String &>(x);
|
||||
set(s);
|
||||
}
|
||||
|
||||
void SettingFieldURI::set(const String & x)
|
||||
{
|
||||
set(Poco::URI(x));
|
||||
}
|
||||
|
||||
void SettingFieldURI::serialize(WriteBuffer & buf, SettingsBinaryFormat) const
|
||||
{
|
||||
writeStringBinary(toString(), buf);
|
||||
}
|
||||
|
||||
void SettingFieldURI::deserialize(ReadBuffer & buf, SettingsBinaryFormat)
|
||||
{
|
||||
String s;
|
||||
readStringBinary(s, buf);
|
||||
set(s);
|
||||
}
|
||||
|
||||
|
||||
#define IMPLEMENT_SETTING_ENUM(ENUM_NAME, LIST_OF_NAMES_MACRO, ERROR_CODE_FOR_UNEXPECTED_NAME) \
|
||||
IMPLEMENT_SETTING_ENUM_WITH_TAG(ENUM_NAME, void, LIST_OF_NAMES_MACRO, ERROR_CODE_FOR_UNEXPECTED_NAME)
|
||||
|
||||
#define IMPLEMENT_SETTING_ENUM_WITH_TAG(ENUM_NAME, TAG, LIST_OF_NAMES_MACRO, ERROR_CODE_FOR_UNEXPECTED_NAME) \
|
||||
template <> \
|
||||
String SettingFieldEnum<ENUM_NAME, TAG>::toString() const \
|
||||
{ \
|
||||
using EnumType = ENUM_NAME; \
|
||||
using UnderlyingType = std::underlying_type<EnumType>::type; \
|
||||
switch (static_cast<UnderlyingType>(value)) \
|
||||
{ \
|
||||
LIST_OF_NAMES_MACRO(IMPLEMENT_SETTING_ENUM_TO_STRING_HELPER_) \
|
||||
} \
|
||||
throw Exception("Unknown " #ENUM_NAME, ERROR_CODE_FOR_UNEXPECTED_NAME); \
|
||||
} \
|
||||
\
|
||||
template <> \
|
||||
void SettingFieldEnum<ENUM_NAME, TAG>::set(const String & s) \
|
||||
{ \
|
||||
using EnumType = ENUM_NAME; \
|
||||
LIST_OF_NAMES_MACRO(IMPLEMENT_SETTING_ENUM_FROM_STRING_HELPER_) \
|
||||
\
|
||||
String all_io_names; \
|
||||
LIST_OF_NAMES_MACRO(IMPLEMENT_SETTING_ENUM_CONCAT_NAMES_HELPER_) \
|
||||
throw Exception("Unknown " #ENUM_NAME " : '" + s + "', must be one of " + all_io_names, \
|
||||
ERROR_CODE_FOR_UNEXPECTED_NAME); \
|
||||
} \
|
||||
\
|
||||
template struct SettingFieldEnum<ENUM_NAME, TAG>;
|
||||
|
||||
#define IMPLEMENT_SETTING_ENUM_TO_STRING_HELPER_(NAME, IO_NAME) \
|
||||
case static_cast<UnderlyingType>(EnumType::NAME): return IO_NAME;
|
||||
|
||||
#define IMPLEMENT_SETTING_ENUM_FROM_STRING_HELPER_(NAME, IO_NAME) \
|
||||
if (s == (IO_NAME)) \
|
||||
{ \
|
||||
set(EnumType::NAME); \
|
||||
return; \
|
||||
}
|
||||
|
||||
#define IMPLEMENT_SETTING_ENUM_CONCAT_NAMES_HELPER_(NAME, IO_NAME) \
|
||||
if (!all_io_names.empty()) \
|
||||
all_io_names += ", "; \
|
||||
all_io_names += String("'") + (IO_NAME) + "'";
|
||||
|
||||
|
||||
#define LOAD_BALANCING_LIST_OF_NAMES(M) \
|
||||
M(RANDOM, "random") \
|
||||
M(NEAREST_HOSTNAME, "nearest_hostname") \
|
||||
M(IN_ORDER, "in_order") \
|
||||
M(FIRST_OR_RANDOM, "first_or_random") \
|
||||
M(ROUND_ROBIN, "round_robin")
|
||||
IMPLEMENT_SETTING_ENUM(LoadBalancing, LOAD_BALANCING_LIST_OF_NAMES, ErrorCodes::UNKNOWN_LOAD_BALANCING)
|
||||
|
||||
|
||||
#define SPECIAL_SORT_ALGORITHM_NAMES(M) \
|
||||
M(NOT_SPECIFIED, "not_specified") \
|
||||
M(OPENCL_BITONIC, "opencl_bitonic")
|
||||
IMPLEMENT_SETTING_ENUM(SpecialSort, SPECIAL_SORT_ALGORITHM_NAMES, ErrorCodes::UNKNOWN_JOIN)
|
||||
|
||||
|
||||
#define JOIN_STRICTNESS_LIST_OF_NAMES(M) \
|
||||
M(Unspecified, "") \
|
||||
M(ALL, "ALL") \
|
||||
M(ANY, "ANY")
|
||||
IMPLEMENT_SETTING_ENUM(JoinStrictness, JOIN_STRICTNESS_LIST_OF_NAMES, ErrorCodes::UNKNOWN_JOIN) // NOLINT
|
||||
|
||||
#define JOIN_ALGORITHM_NAMES(M) \
|
||||
M(AUTO, "auto") \
|
||||
M(HASH, "hash") \
|
||||
M(PARTIAL_MERGE, "partial_merge") \
|
||||
M(PREFER_PARTIAL_MERGE, "prefer_partial_merge")
|
||||
IMPLEMENT_SETTING_ENUM(JoinAlgorithm, JOIN_ALGORITHM_NAMES, ErrorCodes::UNKNOWN_JOIN)
|
||||
|
||||
#define TOTALS_MODE_LIST_OF_NAMES(M) \
|
||||
M(BEFORE_HAVING, "before_having") \
|
||||
M(AFTER_HAVING_EXCLUSIVE, "after_having_exclusive") \
|
||||
M(AFTER_HAVING_INCLUSIVE, "after_having_inclusive") \
|
||||
M(AFTER_HAVING_AUTO, "after_having_auto")
|
||||
IMPLEMENT_SETTING_ENUM(TotalsMode, TOTALS_MODE_LIST_OF_NAMES, ErrorCodes::UNKNOWN_TOTALS_MODE)
|
||||
|
||||
|
||||
#define OVERFLOW_MODE_LIST_OF_NAMES(M) \
|
||||
M(THROW, "throw") \
|
||||
M(BREAK, "break")
|
||||
IMPLEMENT_SETTING_ENUM(OverflowMode, OVERFLOW_MODE_LIST_OF_NAMES, ErrorCodes::UNKNOWN_OVERFLOW_MODE)
|
||||
|
||||
|
||||
#define OVERFLOW_MODE_LIST_OF_NAMES_WITH_ANY(M) \
|
||||
M(THROW, "throw") \
|
||||
M(BREAK, "break") \
|
||||
M(ANY, "any")
|
||||
IMPLEMENT_SETTING_ENUM_WITH_TAG(OverflowMode, SettingFieldOverflowModeGroupByTag, OVERFLOW_MODE_LIST_OF_NAMES_WITH_ANY, ErrorCodes::UNKNOWN_OVERFLOW_MODE)
|
||||
|
||||
|
||||
#define DISTRIBUTED_PRODUCT_MODE_LIST_OF_NAMES(M) \
|
||||
M(DENY, "deny") \
|
||||
M(LOCAL, "local") \
|
||||
M(GLOBAL, "global") \
|
||||
M(ALLOW, "allow")
|
||||
IMPLEMENT_SETTING_ENUM(DistributedProductMode, DISTRIBUTED_PRODUCT_MODE_LIST_OF_NAMES, ErrorCodes::UNKNOWN_DISTRIBUTED_PRODUCT_MODE)
|
||||
|
||||
|
||||
#define DATE_TIME_INPUT_FORMAT_LIST_OF_NAMES(M) \
|
||||
M(Basic, "basic") \
|
||||
M(BestEffort, "best_effort")
|
||||
IMPLEMENT_SETTING_ENUM(FormatSettings::DateTimeInputFormat, DATE_TIME_INPUT_FORMAT_LIST_OF_NAMES, ErrorCodes::BAD_ARGUMENTS)
|
||||
|
||||
|
||||
#define LOGS_LEVEL_LIST_OF_NAMES(M) \
|
||||
M(none, "none") \
|
||||
M(fatal, "fatal") \
|
||||
M(error, "error") \
|
||||
M(warning, "warning") \
|
||||
M(information, "information") \
|
||||
M(debug, "debug") \
|
||||
M(trace, "trace")
|
||||
IMPLEMENT_SETTING_ENUM(LogsLevel, LOGS_LEVEL_LIST_OF_NAMES, ErrorCodes::BAD_ARGUMENTS)
|
||||
|
||||
#define LOG_QUERIES_TYPE_LIST_OF_NAMES(M) \
|
||||
M(QUERY_START, "QUERY_START") \
|
||||
M(QUERY_FINISH, "QUERY_FINISH") \
|
||||
M(EXCEPTION_BEFORE_START, "EXCEPTION_BEFORE_START") \
|
||||
M(EXCEPTION_WHILE_PROCESSING, "EXCEPTION_WHILE_PROCESSING")
|
||||
IMPLEMENT_SETTING_ENUM(QueryLogElementType, LOG_QUERIES_TYPE_LIST_OF_NAMES, ErrorCodes::BAD_ARGUMENTS)
|
||||
|
||||
|
||||
#define DEFAULT_DATABASE_ENGINE_LIST_OF_NAMES(M) \
|
||||
M(Ordinary, "Ordinary") \
|
||||
M(Atomic, "Atomic")
|
||||
IMPLEMENT_SETTING_ENUM(DefaultDatabaseEngine , DEFAULT_DATABASE_ENGINE_LIST_OF_NAMES, ErrorCodes::BAD_ARGUMENTS)
|
||||
|
||||
|
||||
namespace details
|
||||
{
|
||||
void SettingsCollectionUtils::serializeName(const StringRef & name, WriteBuffer & buf)
|
||||
|
|
|
@ -1,11 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <Poco/Timespan.h>
|
||||
#include <Poco/URI.h>
|
||||
#include <DataStreams/SizeLimits.h>
|
||||
#include <Formats/FormatSettings.h>
|
||||
#include <common/StringRef.h>
|
||||
#include <Core/Types.h>
|
||||
#include <Core/SettingsFields.h>
|
||||
#include <unordered_map>
|
||||
|
||||
|
||||
|
@ -17,326 +13,6 @@ struct SettingChange;
|
|||
class SettingsChanges;
|
||||
class ReadBuffer;
|
||||
class WriteBuffer;
|
||||
enum class SettingsBinaryFormat;
|
||||
|
||||
|
||||
/** One setting for any type.
|
||||
* Stores a value within itself, as well as a flag - whether the value was changed.
|
||||
* This is done so that you can send to the remote servers only changed settings (or explicitly specified in the config) values.
|
||||
* That is, if the configuration was not specified in the config and was not dynamically changed, it is not sent to the remote server,
|
||||
* and the remote server will use its default value.
|
||||
*/
|
||||
|
||||
template <typename Type>
|
||||
struct SettingFieldNumber
|
||||
{
|
||||
Type value;
|
||||
bool changed = false;
|
||||
|
||||
SettingFieldNumber(Type x = 0) : value(x) {}
|
||||
|
||||
operator Type() const { return value; }
|
||||
SettingFieldNumber & operator= (Type x) { set(x); return *this; }
|
||||
|
||||
/// Serialize to a test string.
|
||||
String toString() const;
|
||||
|
||||
/// Converts to a field.
|
||||
Field toField() const;
|
||||
|
||||
void set(Type x);
|
||||
|
||||
/// Read from SQL literal.
|
||||
void set(const Field & x);
|
||||
|
||||
/// Read from text string.
|
||||
void set(const String & x);
|
||||
|
||||
/// Serialize to binary stream suitable for transfer over network.
|
||||
void serialize(WriteBuffer & buf, SettingsBinaryFormat format) const;
|
||||
|
||||
/// Read from binary stream.
|
||||
void deserialize(ReadBuffer & buf, SettingsBinaryFormat format);
|
||||
};
|
||||
|
||||
using SettingFieldUInt64 = SettingFieldNumber<UInt64>;
|
||||
using SettingFieldInt64 = SettingFieldNumber<Int64>;
|
||||
using SettingFieldFloat = SettingFieldNumber<float>;
|
||||
using SettingFieldBool = SettingFieldNumber<bool>;
|
||||
|
||||
|
||||
/** Unlike SettingUInt64, supports the value of 'auto' - the number of processor cores without taking into account SMT.
|
||||
* A value of 0 is also treated as auto.
|
||||
* When serializing, `auto` is written in the same way as 0.
|
||||
*/
|
||||
struct SettingFieldMaxThreads
|
||||
{
|
||||
UInt64 value;
|
||||
bool is_auto;
|
||||
bool changed = false;
|
||||
|
||||
SettingFieldMaxThreads(UInt64 x = 0) : value(x ? x : getAutoValue()), is_auto(x == 0) {}
|
||||
|
||||
operator UInt64() const { return value; }
|
||||
SettingFieldMaxThreads & operator= (UInt64 x) { set(x); return *this; }
|
||||
|
||||
String toString() const;
|
||||
Field toField() const;
|
||||
|
||||
void set(UInt64 x);
|
||||
void set(const Field & x);
|
||||
void set(const String & x);
|
||||
|
||||
void serialize(WriteBuffer & buf, SettingsBinaryFormat format) const;
|
||||
void deserialize(ReadBuffer & buf, SettingsBinaryFormat format);
|
||||
|
||||
void setAuto();
|
||||
static UInt64 getAutoValue();
|
||||
};
|
||||
|
||||
|
||||
enum class SettingFieldTimespanIO { MILLISECOND, SECOND };
|
||||
|
||||
template <SettingFieldTimespanIO io_unit>
|
||||
struct SettingFieldTimespan
|
||||
{
|
||||
Poco::Timespan value;
|
||||
bool changed = false;
|
||||
|
||||
SettingFieldTimespan(UInt64 x = 0) : value(x * microseconds_per_io_unit) {}
|
||||
|
||||
operator Poco::Timespan() const { return value; }
|
||||
SettingFieldTimespan & operator=(const Poco::Timespan & x) { set(x); return *this; }
|
||||
|
||||
template <class Rep, class Period = std::ratio<1>>
|
||||
operator std::chrono::duration<Rep, Period>() const { return std::chrono::duration_cast<std::chrono::duration<Rep, Period>>(std::chrono::microseconds(value.totalMicroseconds())); }
|
||||
|
||||
template <class Rep, class Period = std::ratio<1>>
|
||||
SettingFieldTimespan & operator=(const std::chrono::duration<Rep, Period> & x) { set(x); return *this; }
|
||||
|
||||
Poco::Timespan::TimeDiff totalSeconds() const { return value.totalSeconds(); }
|
||||
Poco::Timespan::TimeDiff totalMilliseconds() const { return value.totalMilliseconds(); }
|
||||
|
||||
String toString() const;
|
||||
Field toField() const;
|
||||
|
||||
void set(const Poco::Timespan & x);
|
||||
|
||||
template <class Rep, class Period = std::ratio<1>>
|
||||
void set(const std::chrono::duration<Rep, Period> & duration) { set(static_cast<UInt64>(std::chrono::duration_cast<std::chrono::microseconds>(duration).count())); }
|
||||
|
||||
void set(UInt64 x);
|
||||
void set(const Field & x);
|
||||
void set(const String & x);
|
||||
|
||||
void serialize(WriteBuffer & buf, SettingsBinaryFormat format) const;
|
||||
void deserialize(ReadBuffer & buf, SettingsBinaryFormat format);
|
||||
|
||||
static constexpr UInt64 microseconds_per_io_unit = (io_unit == SettingFieldTimespanIO::MILLISECOND) ? 1000 : 1000000;
|
||||
};
|
||||
|
||||
using SettingFieldSeconds = SettingFieldTimespan<SettingFieldTimespanIO::SECOND>;
|
||||
using SettingFieldMilliseconds = SettingFieldTimespan<SettingFieldTimespanIO::MILLISECOND>;
|
||||
|
||||
|
||||
struct SettingFieldString
|
||||
{
|
||||
String value;
|
||||
bool changed = false;
|
||||
|
||||
SettingFieldString(const String & x = String{}) : value(x) {}
|
||||
|
||||
operator String() const { return value; }
|
||||
SettingFieldString & operator= (const String & x) { set(x); return *this; }
|
||||
|
||||
String toString() const;
|
||||
Field toField() const;
|
||||
|
||||
void set(const String & x);
|
||||
void set(const Field & x);
|
||||
|
||||
void serialize(WriteBuffer & buf, SettingsBinaryFormat format) const;
|
||||
void deserialize(ReadBuffer & buf, SettingsBinaryFormat format);
|
||||
};
|
||||
|
||||
|
||||
struct SettingFieldChar
|
||||
{
|
||||
public:
|
||||
char value;
|
||||
bool changed = false;
|
||||
|
||||
SettingFieldChar(char x = '\0') : value(x) {}
|
||||
|
||||
operator char() const { return value; }
|
||||
SettingFieldChar & operator= (char x) { set(x); return *this; }
|
||||
|
||||
String toString() const;
|
||||
Field toField() const;
|
||||
|
||||
void set(char x);
|
||||
void set(const String & x);
|
||||
void set(const Field & x);
|
||||
|
||||
void serialize(WriteBuffer & buf, SettingsBinaryFormat format) const;
|
||||
void deserialize(ReadBuffer & buf, SettingsBinaryFormat format);
|
||||
};
|
||||
|
||||
|
||||
/// Template class to define enum-based settings.
|
||||
template <typename EnumType, typename Tag = void>
|
||||
struct SettingFieldEnum
|
||||
{
|
||||
EnumType value;
|
||||
bool changed = false;
|
||||
|
||||
SettingFieldEnum(EnumType x) : value(x) {}
|
||||
|
||||
operator EnumType() const { return value; }
|
||||
SettingFieldEnum & operator= (EnumType x) { set(x); return *this; }
|
||||
|
||||
String toString() const;
|
||||
Field toField() const;
|
||||
|
||||
void set(EnumType x) { value = x; changed = true; }
|
||||
void set(const Field & x);
|
||||
void set(const String & x);
|
||||
|
||||
void serialize(WriteBuffer & buf, SettingsBinaryFormat format) const;
|
||||
void deserialize(ReadBuffer & buf, SettingsBinaryFormat format);
|
||||
};
|
||||
|
||||
struct SettingFieldURI
|
||||
{
|
||||
Poco::URI value;
|
||||
bool changed = false;
|
||||
|
||||
SettingFieldURI(const Poco::URI & x = Poco::URI{}) : value(x) {}
|
||||
|
||||
operator Poco::URI() const { return value; }
|
||||
SettingFieldURI & operator= (const Poco::URI & x) { set(x); return *this; }
|
||||
|
||||
String toString() const;
|
||||
Field toField() const;
|
||||
|
||||
void set(const Poco::URI & x);
|
||||
void set(const Field & x);
|
||||
void set(const String & x);
|
||||
|
||||
void serialize(WriteBuffer & buf, SettingsBinaryFormat format) const;
|
||||
void deserialize(ReadBuffer & buf, SettingsBinaryFormat format);
|
||||
};
|
||||
|
||||
enum class LoadBalancing
|
||||
{
|
||||
/// among replicas with a minimum number of errors selected randomly
|
||||
RANDOM = 0,
|
||||
/// a replica is selected among the replicas with the minimum number of errors
|
||||
/// with the minimum number of distinguished characters in the replica name and local hostname
|
||||
NEAREST_HOSTNAME,
|
||||
// replicas with the same number of errors are accessed in the same order
|
||||
// as they are specified in the configuration.
|
||||
IN_ORDER,
|
||||
/// if first replica one has higher number of errors,
|
||||
/// pick a random one from replicas with minimum number of errors
|
||||
FIRST_OR_RANDOM,
|
||||
// round robin across replicas with the same number of errors.
|
||||
ROUND_ROBIN,
|
||||
};
|
||||
using SettingFieldLoadBalancing = SettingFieldEnum<LoadBalancing>;
|
||||
|
||||
|
||||
enum class JoinStrictness
|
||||
{
|
||||
Unspecified = 0, /// Query JOIN without strictness will throw Exception.
|
||||
ALL, /// Query JOIN without strictness -> ALL JOIN ...
|
||||
ANY, /// Query JOIN without strictness -> ANY JOIN ...
|
||||
};
|
||||
using SettingFieldJoinStrictness = SettingFieldEnum<JoinStrictness>;
|
||||
|
||||
enum class JoinAlgorithm
|
||||
{
|
||||
AUTO = 0,
|
||||
HASH,
|
||||
PARTIAL_MERGE,
|
||||
PREFER_PARTIAL_MERGE,
|
||||
};
|
||||
using SettingFieldJoinAlgorithm = SettingFieldEnum<JoinAlgorithm>;
|
||||
|
||||
|
||||
enum class SpecialSort
|
||||
{
|
||||
NOT_SPECIFIED = 0,
|
||||
OPENCL_BITONIC,
|
||||
};
|
||||
using SettingFieldSpecialSort = SettingFieldEnum<SpecialSort>;
|
||||
|
||||
|
||||
/// Which rows should be included in TOTALS.
|
||||
enum class TotalsMode
|
||||
{
|
||||
BEFORE_HAVING = 0, /// Count HAVING for all read rows;
|
||||
/// including those not in max_rows_to_group_by
|
||||
/// and have not passed HAVING after grouping.
|
||||
AFTER_HAVING_INCLUSIVE = 1, /// Count on all rows except those that have not passed HAVING;
|
||||
/// that is, to include in TOTALS all the rows that did not pass max_rows_to_group_by.
|
||||
AFTER_HAVING_EXCLUSIVE = 2, /// Include only the rows that passed and max_rows_to_group_by, and HAVING.
|
||||
AFTER_HAVING_AUTO = 3, /// Automatically select between INCLUSIVE and EXCLUSIVE,
|
||||
};
|
||||
using SettingFieldTotalsMode = SettingFieldEnum<TotalsMode>;
|
||||
|
||||
|
||||
/// The settings keeps OverflowMode which cannot be OverflowMode::ANY.
|
||||
using SettingFieldOverflowMode = SettingFieldEnum<OverflowMode>;
|
||||
struct SettingFieldOverflowModeGroupByTag;
|
||||
|
||||
/// The settings keeps OverflowMode which can be OverflowMode::ANY.
|
||||
using SettingFieldOverflowModeGroupBy = SettingFieldEnum<OverflowMode, SettingFieldOverflowModeGroupByTag>;
|
||||
|
||||
|
||||
/// The setting for executing distributed subqueries inside IN or JOIN sections.
|
||||
enum class DistributedProductMode
|
||||
{
|
||||
DENY = 0, /// Disable
|
||||
LOCAL, /// Convert to local query
|
||||
GLOBAL, /// Convert to global query
|
||||
ALLOW /// Enable
|
||||
};
|
||||
using SettingFieldDistributedProductMode = SettingFieldEnum<DistributedProductMode>;
|
||||
|
||||
|
||||
using SettingFieldDateTimeInputFormat = SettingFieldEnum<FormatSettings::DateTimeInputFormat>;
|
||||
|
||||
|
||||
enum class LogsLevel
|
||||
{
|
||||
none = 0, /// Disable
|
||||
fatal,
|
||||
error,
|
||||
warning,
|
||||
information,
|
||||
debug,
|
||||
trace,
|
||||
};
|
||||
using SettingFieldLogsLevel = SettingFieldEnum<LogsLevel>;
|
||||
|
||||
enum class DefaultDatabaseEngine
|
||||
{
|
||||
Ordinary,
|
||||
Atomic,
|
||||
};
|
||||
using SettingFieldDefaultDatabaseEngine = SettingFieldEnum<DefaultDatabaseEngine>;
|
||||
|
||||
// Make it signed for compatibility with DataTypeEnum8
|
||||
enum QueryLogElementType : int8_t
|
||||
{
|
||||
QUERY_START = 1,
|
||||
QUERY_FINISH = 2,
|
||||
EXCEPTION_BEFORE_START = 3,
|
||||
EXCEPTION_WHILE_PROCESSING = 4,
|
||||
};
|
||||
using SettingFieldLogQueriesType = SettingFieldEnum<QueryLogElementType>;
|
||||
|
||||
|
||||
enum class SettingsBinaryFormat
|
||||
{
|
||||
|
@ -377,8 +53,8 @@ private:
|
|||
using GetFieldFunction = Field (*)(const Derived &);
|
||||
using SetStringFunction = void (*)(Derived &, const String &);
|
||||
using SetFieldFunction = void (*)(Derived &, const Field &);
|
||||
using SerializeFunction = void (*)(const Derived &, WriteBuffer & buf, SettingsBinaryFormat);
|
||||
using DeserializeFunction = void (*)(Derived &, ReadBuffer & buf, SettingsBinaryFormat);
|
||||
using WriteBinaryFunction = void (*)(const Derived &, WriteBuffer & buf);
|
||||
using ReadBinaryFunction = void (*)(Derived &, ReadBuffer & buf);
|
||||
using ValueToStringFunction = String (*)(const Field &);
|
||||
using ValueToCorrespondingTypeFunction = Field (*)(const Field &);
|
||||
|
||||
|
@ -391,8 +67,8 @@ private:
|
|||
GetFieldFunction get_field;
|
||||
SetStringFunction set_string;
|
||||
SetFieldFunction set_field;
|
||||
SerializeFunction serialize;
|
||||
DeserializeFunction deserialize;
|
||||
WriteBinaryFunction write_binary;
|
||||
ReadBinaryFunction read_binary;
|
||||
ValueToStringFunction value_to_string;
|
||||
ValueToCorrespondingTypeFunction value_to_corresponding_type;
|
||||
};
|
||||
|
|
|
@ -278,8 +278,12 @@ void SettingsCollection<Derived>::serialize(WriteBuffer & buf, SettingsBinaryFor
|
|||
{
|
||||
details::SettingsCollectionUtils::serializeName(member.name, buf);
|
||||
if (format >= SettingsBinaryFormat::STRINGS)
|
||||
{
|
||||
details::SettingsCollectionUtils::serializeFlag(member.is_important, buf);
|
||||
member.serialize(castToDerived(), buf, format);
|
||||
details::SettingsCollectionUtils::serializeName(member.get_string(castToDerived()), buf);
|
||||
}
|
||||
else
|
||||
member.write_binary(castToDerived(), buf);
|
||||
}
|
||||
}
|
||||
details::SettingsCollectionUtils::serializeName(StringRef{} /* empty string is a marker of the end of settings */, buf);
|
||||
|
@ -296,20 +300,30 @@ void SettingsCollection<Derived>::deserialize(ReadBuffer & buf, SettingsBinaryFo
|
|||
if (name.empty() /* empty string is a marker of the end of settings */)
|
||||
break;
|
||||
auto * member = the_members.find(name);
|
||||
bool is_important = (format >= SettingsBinaryFormat::STRINGS) ? details::SettingsCollectionUtils::deserializeFlag(buf) : true;
|
||||
if (member)
|
||||
bool is_important = true;
|
||||
if (format >= SettingsBinaryFormat::STRINGS)
|
||||
is_important = details::SettingsCollectionUtils::deserializeFlag(buf);
|
||||
if (!member)
|
||||
{
|
||||
member->deserialize(castToDerived(), buf, format);
|
||||
if (is_important)
|
||||
{
|
||||
details::SettingsCollectionUtils::throwNameNotFound(name);
|
||||
}
|
||||
else
|
||||
{
|
||||
details::SettingsCollectionUtils::warningNameNotFound(name);
|
||||
details::SettingsCollectionUtils::skipValue(buf);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (is_important)
|
||||
|
||||
if (format >= SettingsBinaryFormat::STRINGS)
|
||||
{
|
||||
details::SettingsCollectionUtils::throwNameNotFound(name);
|
||||
String value = details::SettingsCollectionUtils::deserializeName(buf);
|
||||
member->set_string(castToDerived(), value);
|
||||
}
|
||||
else
|
||||
{
|
||||
details::SettingsCollectionUtils::warningNameNotFound(name);
|
||||
details::SettingsCollectionUtils::skipValue(buf);
|
||||
}
|
||||
member->read_binary(castToDerived(), buf);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -340,8 +354,8 @@ void SettingsCollection<Derived>::deserialize(ReadBuffer & buf, SettingsBinaryFo
|
|||
static Field NAME##_getField(const Derived & collection) { return collection.NAME.toField(); } \
|
||||
static void NAME##_setString(Derived & collection, const String & value) { collection.NAME.set(value); } \
|
||||
static void NAME##_setField(Derived & collection, const Field & value) { collection.NAME.set(value); } \
|
||||
static void NAME##_serialize(const Derived & collection, WriteBuffer & buf, SettingsBinaryFormat format) { collection.NAME.serialize(buf, format); } \
|
||||
static void NAME##_deserialize(Derived & collection, ReadBuffer & buf, SettingsBinaryFormat format) { collection.NAME.deserialize(buf, format); } \
|
||||
static void NAME##_writeBinary(const Derived & collection, WriteBuffer & buf) { collection.NAME.writeBinary(buf); } \
|
||||
static void NAME##_readBinary(Derived & collection, ReadBuffer & buf) { collection.NAME.readBinary(buf); } \
|
||||
static String NAME##_valueToString(const Field & value) { SettingField##TYPE temp{DEFAULT}; temp.set(value); return temp.toString(); } \
|
||||
static Field NAME##_valueToCorrespondingType(const Field & value) { SettingField##TYPE temp{DEFAULT}; temp.set(value); return temp.toField(); } \
|
||||
|
||||
|
@ -354,6 +368,6 @@ void SettingsCollection<Derived>::deserialize(ReadBuffer & buf, SettingsBinaryFo
|
|||
[](const Derived & d) { return d.NAME.changed; }, \
|
||||
&Functions::NAME##_getString, &Functions::NAME##_getField, \
|
||||
&Functions::NAME##_setString, &Functions::NAME##_setField, \
|
||||
&Functions::NAME##_serialize, &Functions::NAME##_deserialize, \
|
||||
&Functions::NAME##_writeBinary, &Functions::NAME##_readBinary, \
|
||||
&Functions::NAME##_valueToString, &Functions::NAME##_valueToCorrespondingType});
|
||||
}
|
||||
|
|
|
@ -0,0 +1,94 @@
|
|||
#include <Core/SettingsEnums.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
{
|
||||
namespace ErrorCodes
|
||||
{
|
||||
extern const int UNKNOWN_LOAD_BALANCING;
|
||||
extern const int UNKNOWN_OVERFLOW_MODE;
|
||||
extern const int UNKNOWN_TOTALS_MODE;
|
||||
extern const int UNKNOWN_DISTRIBUTED_PRODUCT_MODE;
|
||||
extern const int UNKNOWN_JOIN;
|
||||
extern const int BAD_ARGUMENTS;
|
||||
}
|
||||
|
||||
|
||||
IMPLEMENT_SETTING_ENUM(LoadBalancing, ErrorCodes::UNKNOWN_LOAD_BALANCING,
|
||||
{{"random", LoadBalancing::RANDOM},
|
||||
{"nearest_hostname", LoadBalancing::NEAREST_HOSTNAME},
|
||||
{"in_order", LoadBalancing::IN_ORDER},
|
||||
{"first_or_random", LoadBalancing::FIRST_OR_RANDOM},
|
||||
{"round_robin", LoadBalancing::ROUND_ROBIN}})
|
||||
|
||||
|
||||
IMPLEMENT_SETTING_ENUM(SpecialSort, ErrorCodes::UNKNOWN_JOIN,
|
||||
{{"not_specified", SpecialSort::NOT_SPECIFIED},
|
||||
{"opencl_bitonic", SpecialSort::OPENCL_BITONIC}})
|
||||
|
||||
|
||||
IMPLEMENT_SETTING_ENUM(JoinStrictness, ErrorCodes::UNKNOWN_JOIN,
|
||||
{{"", JoinStrictness::Unspecified},
|
||||
{"ALL", JoinStrictness::ALL},
|
||||
{"ANY", JoinStrictness::ANY}})
|
||||
|
||||
|
||||
IMPLEMENT_SETTING_ENUM(JoinAlgorithm, ErrorCodes::UNKNOWN_JOIN,
|
||||
{{"auto", JoinAlgorithm::AUTO},
|
||||
{"hash", JoinAlgorithm::HASH},
|
||||
{"partial_merge", JoinAlgorithm::PARTIAL_MERGE},
|
||||
{"prefer_partial_merge", JoinAlgorithm::PREFER_PARTIAL_MERGE}})
|
||||
|
||||
|
||||
IMPLEMENT_SETTING_ENUM(TotalsMode, ErrorCodes::UNKNOWN_TOTALS_MODE,
|
||||
{{"before_having", TotalsMode::BEFORE_HAVING},
|
||||
{"after_having_exclusive", TotalsMode::AFTER_HAVING_EXCLUSIVE},
|
||||
{"after_having_inclusive", TotalsMode::AFTER_HAVING_INCLUSIVE},
|
||||
{"after_having_auto", TotalsMode::AFTER_HAVING_AUTO}})
|
||||
|
||||
|
||||
IMPLEMENT_SETTING_ENUM(OverflowMode, ErrorCodes::UNKNOWN_OVERFLOW_MODE,
|
||||
{{"throw", OverflowMode::THROW},
|
||||
{"break", OverflowMode::BREAK}})
|
||||
|
||||
|
||||
IMPLEMENT_SETTING_ENUM_WITH_RENAME(OverflowModeGroupBy, ErrorCodes::UNKNOWN_OVERFLOW_MODE,
|
||||
{{"throw", OverflowMode::THROW},
|
||||
{"break", OverflowMode::BREAK},
|
||||
{"any", OverflowMode::ANY}})
|
||||
|
||||
|
||||
IMPLEMENT_SETTING_ENUM(DistributedProductMode, ErrorCodes::UNKNOWN_DISTRIBUTED_PRODUCT_MODE,
|
||||
{{"deny", DistributedProductMode::DENY},
|
||||
{"local", DistributedProductMode::LOCAL},
|
||||
{"global", DistributedProductMode::GLOBAL},
|
||||
{"allow", DistributedProductMode::ALLOW}})
|
||||
|
||||
|
||||
IMPLEMENT_SETTING_ENUM_WITH_RENAME(DateTimeInputFormat, ErrorCodes::BAD_ARGUMENTS,
|
||||
{{"basic", FormatSettings::DateTimeInputFormat::Basic},
|
||||
{"best_effort", FormatSettings::DateTimeInputFormat::BestEffort}})
|
||||
|
||||
|
||||
IMPLEMENT_SETTING_ENUM(LogsLevel, ErrorCodes::BAD_ARGUMENTS,
|
||||
{{"none", LogsLevel::none},
|
||||
{"fatal", LogsLevel::fatal},
|
||||
{"error", LogsLevel::error},
|
||||
{"warning", LogsLevel::warning},
|
||||
{"information", LogsLevel::information},
|
||||
{"debug", LogsLevel::debug},
|
||||
{"trace", LogsLevel::trace}})
|
||||
|
||||
|
||||
IMPLEMENT_SETTING_ENUM_WITH_RENAME(LogQueriesType, ErrorCodes::BAD_ARGUMENTS,
|
||||
{{"QUERY_START", QUERY_START},
|
||||
{"QUERY_FINISH", QUERY_FINISH},
|
||||
{"EXCEPTION_BEFORE_START", EXCEPTION_BEFORE_START},
|
||||
{"EXCEPTION_WHILE_PROCESSING", EXCEPTION_WHILE_PROCESSING}})
|
||||
|
||||
|
||||
IMPLEMENT_SETTING_ENUM_WITH_RENAME(DefaultDatabaseEngine, ErrorCodes::BAD_ARGUMENTS,
|
||||
{{"Ordinary", DefaultDatabaseEngine::Ordinary},
|
||||
{"Atomic", DefaultDatabaseEngine::Atomic}})
|
||||
|
||||
}
|
|
@ -0,0 +1,129 @@
|
|||
#pragma once
|
||||
|
||||
#include <Core/SettingsFields.h>
|
||||
#include <DataStreams/SizeLimits.h>
|
||||
#include <Formats/FormatSettings.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
{
|
||||
enum class LoadBalancing
|
||||
{
|
||||
/// among replicas with a minimum number of errors selected randomly
|
||||
RANDOM = 0,
|
||||
/// a replica is selected among the replicas with the minimum number of errors
|
||||
/// with the minimum number of distinguished characters in the replica name and local hostname
|
||||
NEAREST_HOSTNAME,
|
||||
// replicas with the same number of errors are accessed in the same order
|
||||
// as they are specified in the configuration.
|
||||
IN_ORDER,
|
||||
/// if first replica one has higher number of errors,
|
||||
/// pick a random one from replicas with minimum number of errors
|
||||
FIRST_OR_RANDOM,
|
||||
// round robin across replicas with the same number of errors.
|
||||
ROUND_ROBIN,
|
||||
};
|
||||
|
||||
DECLARE_SETTING_ENUM(LoadBalancing)
|
||||
|
||||
|
||||
enum class JoinStrictness
|
||||
{
|
||||
Unspecified = 0, /// Query JOIN without strictness will throw Exception.
|
||||
ALL, /// Query JOIN without strictness -> ALL JOIN ...
|
||||
ANY, /// Query JOIN without strictness -> ANY JOIN ...
|
||||
};
|
||||
|
||||
DECLARE_SETTING_ENUM(JoinStrictness)
|
||||
|
||||
enum class JoinAlgorithm
|
||||
{
|
||||
AUTO = 0,
|
||||
HASH,
|
||||
PARTIAL_MERGE,
|
||||
PREFER_PARTIAL_MERGE,
|
||||
};
|
||||
|
||||
DECLARE_SETTING_ENUM(JoinAlgorithm)
|
||||
|
||||
|
||||
enum class SpecialSort
|
||||
{
|
||||
NOT_SPECIFIED = 0,
|
||||
OPENCL_BITONIC,
|
||||
};
|
||||
|
||||
DECLARE_SETTING_ENUM(SpecialSort)
|
||||
|
||||
|
||||
/// Which rows should be included in TOTALS.
|
||||
enum class TotalsMode
|
||||
{
|
||||
BEFORE_HAVING = 0, /// Count HAVING for all read rows;
|
||||
/// including those not in max_rows_to_group_by
|
||||
/// and have not passed HAVING after grouping.
|
||||
AFTER_HAVING_INCLUSIVE = 1, /// Count on all rows except those that have not passed HAVING;
|
||||
/// that is, to include in TOTALS all the rows that did not pass max_rows_to_group_by.
|
||||
AFTER_HAVING_EXCLUSIVE = 2, /// Include only the rows that passed and max_rows_to_group_by, and HAVING.
|
||||
AFTER_HAVING_AUTO = 3, /// Automatically select between INCLUSIVE and EXCLUSIVE,
|
||||
};
|
||||
|
||||
DECLARE_SETTING_ENUM(TotalsMode)
|
||||
|
||||
|
||||
/// The settings keeps OverflowMode which cannot be OverflowMode::ANY.
|
||||
DECLARE_SETTING_ENUM(OverflowMode)
|
||||
|
||||
/// The settings keeps OverflowMode which can be OverflowMode::ANY.
|
||||
DECLARE_SETTING_ENUM_WITH_RENAME(OverflowModeGroupBy, OverflowMode)
|
||||
|
||||
|
||||
/// The setting for executing distributed subqueries inside IN or JOIN sections.
|
||||
enum class DistributedProductMode
|
||||
{
|
||||
DENY = 0, /// Disable
|
||||
LOCAL, /// Convert to local query
|
||||
GLOBAL, /// Convert to global query
|
||||
ALLOW /// Enable
|
||||
};
|
||||
|
||||
DECLARE_SETTING_ENUM(DistributedProductMode)
|
||||
|
||||
|
||||
DECLARE_SETTING_ENUM_WITH_RENAME(DateTimeInputFormat, FormatSettings::DateTimeInputFormat)
|
||||
|
||||
|
||||
enum class LogsLevel
|
||||
{
|
||||
none = 0, /// Disable
|
||||
fatal,
|
||||
error,
|
||||
warning,
|
||||
information,
|
||||
debug,
|
||||
trace,
|
||||
};
|
||||
|
||||
DECLARE_SETTING_ENUM(LogsLevel)
|
||||
|
||||
|
||||
// Make it signed for compatibility with DataTypeEnum8
|
||||
enum QueryLogElementType : int8_t
|
||||
{
|
||||
QUERY_START = 1,
|
||||
QUERY_FINISH = 2,
|
||||
EXCEPTION_BEFORE_START = 3,
|
||||
EXCEPTION_WHILE_PROCESSING = 4,
|
||||
};
|
||||
|
||||
DECLARE_SETTING_ENUM_WITH_RENAME(LogQueriesType, QueryLogElementType)
|
||||
|
||||
|
||||
enum class DefaultDatabaseEngine
|
||||
{
|
||||
Ordinary,
|
||||
Atomic,
|
||||
};
|
||||
|
||||
DECLARE_SETTING_ENUM(DefaultDatabaseEngine)
|
||||
}
|
|
@ -0,0 +1,365 @@
|
|||
#include <Core/SettingsFields.h>
|
||||
|
||||
#include <Core/Field.h>
|
||||
#include <Common/getNumberOfPhysicalCPUCores.h>
|
||||
#include <Common/FieldVisitors.h>
|
||||
#include <common/logger_useful.h>
|
||||
#include <IO/ReadHelpers.h>
|
||||
#include <IO/ReadBufferFromString.h>
|
||||
#include <IO/WriteHelpers.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
{
|
||||
namespace ErrorCodes
|
||||
{
|
||||
extern const int SIZE_OF_FIXED_STRING_DOESNT_MATCH;
|
||||
extern const int CANNOT_PARSE_BOOL;
|
||||
}
|
||||
|
||||
|
||||
template <typename Type>
|
||||
String SettingFieldNumber<Type>::toString() const
|
||||
{
|
||||
return DB::toString(value);
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
Field SettingFieldNumber<Type>::toField() const
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
void SettingFieldNumber<Type>::set(Type x)
|
||||
{
|
||||
value = x;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
void SettingFieldNumber<Type>::set(const Field & x)
|
||||
{
|
||||
if (x.getType() == Field::Types::String)
|
||||
set(get<const String &>(x));
|
||||
else
|
||||
set(applyVisitor(FieldVisitorConvertToNumber<Type>(), x));
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
void SettingFieldNumber<Type>::set(const String & x)
|
||||
{
|
||||
set(parseWithSizeSuffix<Type>(x));
|
||||
}
|
||||
|
||||
template <>
|
||||
void SettingFieldNumber<bool>::set(const String & x)
|
||||
{
|
||||
if (x.size() == 1)
|
||||
{
|
||||
if (x[0] == '0')
|
||||
set(false);
|
||||
else if (x[0] == '1')
|
||||
set(true);
|
||||
else
|
||||
throw Exception("Cannot parse bool from string '" + x + "'", ErrorCodes::CANNOT_PARSE_BOOL);
|
||||
}
|
||||
else
|
||||
{
|
||||
ReadBufferFromString buf(x);
|
||||
if (checkStringCaseInsensitive("true", buf))
|
||||
set(true);
|
||||
else if (checkStringCaseInsensitive("false", buf))
|
||||
set(false);
|
||||
else
|
||||
throw Exception("Cannot parse bool from string '" + x + "'", ErrorCodes::CANNOT_PARSE_BOOL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <typename Type>
|
||||
void SettingFieldNumber<Type>::writeBinary(WriteBuffer & out) const
|
||||
{
|
||||
if constexpr (is_integral_v<Type> && is_unsigned_v<Type>)
|
||||
writeVarUInt(static_cast<UInt64>(value), out);
|
||||
else if constexpr (is_integral_v<Type> && is_signed_v<Type>)
|
||||
writeVarInt(static_cast<Int64>(value), out);
|
||||
else
|
||||
{
|
||||
static_assert(std::is_floating_point_v<Type>);
|
||||
writeStringBinary(toString(), out);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
void SettingFieldNumber<Type>::readBinary(ReadBuffer & in)
|
||||
{
|
||||
if constexpr (is_integral_v<Type> && is_unsigned_v<Type>)
|
||||
{
|
||||
UInt64 x;
|
||||
readVarUInt(x, in);
|
||||
set(static_cast<Type>(x));
|
||||
}
|
||||
else if constexpr (is_integral_v<Type> && is_signed_v<Type>)
|
||||
{
|
||||
Int64 x;
|
||||
readVarInt(x, in);
|
||||
set(static_cast<Type>(x));
|
||||
}
|
||||
else
|
||||
{
|
||||
static_assert(std::is_floating_point_v<Type>);
|
||||
String x;
|
||||
readStringBinary(x, in);
|
||||
set(x);
|
||||
}
|
||||
}
|
||||
|
||||
template struct SettingFieldNumber<UInt64>;
|
||||
template struct SettingFieldNumber<Int64>;
|
||||
template struct SettingFieldNumber<float>;
|
||||
template struct SettingFieldNumber<bool>;
|
||||
|
||||
|
||||
String SettingFieldMaxThreads::toString() const
|
||||
{
|
||||
/// Instead of the `auto` value, we output the actual value to make it easier to see.
|
||||
return is_auto ? ("auto(" + DB::toString(value) + ")") : DB::toString(value);
|
||||
}
|
||||
|
||||
Field SettingFieldMaxThreads::toField() const
|
||||
{
|
||||
return is_auto ? 0 : value;
|
||||
}
|
||||
|
||||
void SettingFieldMaxThreads::set(UInt64 x)
|
||||
{
|
||||
value = x ? x : getAutoValue();
|
||||
is_auto = x == 0;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
void SettingFieldMaxThreads::set(const Field & x)
|
||||
{
|
||||
if (x.getType() == Field::Types::String)
|
||||
set(get<const String &>(x));
|
||||
else
|
||||
set(applyVisitor(FieldVisitorConvertToNumber<UInt64>(), x));
|
||||
}
|
||||
|
||||
void SettingFieldMaxThreads::set(const String & x)
|
||||
{
|
||||
if (startsWith(x, "auto"))
|
||||
setAuto();
|
||||
else
|
||||
set(parse<UInt64>(x));
|
||||
}
|
||||
|
||||
void SettingFieldMaxThreads::setAuto()
|
||||
{
|
||||
value = getAutoValue();
|
||||
is_auto = true;
|
||||
}
|
||||
|
||||
UInt64 SettingFieldMaxThreads::getAutoValue()
|
||||
{
|
||||
static auto res = getNumberOfPhysicalCPUCores();
|
||||
return res;
|
||||
}
|
||||
|
||||
void SettingFieldMaxThreads::writeBinary(WriteBuffer & out) const
|
||||
{
|
||||
writeVarUInt(is_auto ? 0 : value, out);
|
||||
}
|
||||
|
||||
void SettingFieldMaxThreads::readBinary(ReadBuffer & in)
|
||||
{
|
||||
UInt64 x = 0;
|
||||
readVarUInt(x, in);
|
||||
set(x);
|
||||
}
|
||||
|
||||
|
||||
template <SettingFieldTimespanUnit unit>
|
||||
String SettingFieldTimespan<unit>::toString() const
|
||||
{
|
||||
return DB::toString(value.totalMicroseconds() / microseconds_per_unit);
|
||||
}
|
||||
|
||||
template <SettingFieldTimespanUnit unit>
|
||||
Field SettingFieldTimespan<unit>::toField() const
|
||||
{
|
||||
return value.totalMicroseconds() / microseconds_per_unit;
|
||||
}
|
||||
|
||||
template <SettingFieldTimespanUnit unit>
|
||||
void SettingFieldTimespan<unit>::set(const Poco::Timespan & x)
|
||||
{
|
||||
value = x;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
template <SettingFieldTimespanUnit unit>
|
||||
void SettingFieldTimespan<unit>::set(UInt64 x)
|
||||
{
|
||||
set(Poco::Timespan(x * microseconds_per_unit));
|
||||
}
|
||||
|
||||
template <SettingFieldTimespanUnit unit>
|
||||
void SettingFieldTimespan<unit>::set(const Field & x)
|
||||
{
|
||||
if (x.getType() == Field::Types::String)
|
||||
set(get<const String &>(x));
|
||||
else
|
||||
set(applyVisitor(FieldVisitorConvertToNumber<UInt64>(), x));
|
||||
}
|
||||
|
||||
template <SettingFieldTimespanUnit unit>
|
||||
void SettingFieldTimespan<unit>::set(const String & x)
|
||||
{
|
||||
set(parse<UInt64>(x));
|
||||
}
|
||||
|
||||
template <SettingFieldTimespanUnit unit>
|
||||
void SettingFieldTimespan<unit>::writeBinary(WriteBuffer & out) const
|
||||
{
|
||||
writeVarUInt(value.totalMicroseconds() / microseconds_per_unit, out);
|
||||
}
|
||||
|
||||
template <SettingFieldTimespanUnit unit>
|
||||
void SettingFieldTimespan<unit>::readBinary(ReadBuffer & in)
|
||||
{
|
||||
UInt64 x = 0;
|
||||
readVarUInt(x, in);
|
||||
set(x);
|
||||
}
|
||||
|
||||
template struct SettingFieldTimespan<SettingFieldTimespanUnit::SECOND>;
|
||||
template struct SettingFieldTimespan<SettingFieldTimespanUnit::MILLISECOND>;
|
||||
|
||||
|
||||
Field SettingFieldString::toField() const
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
void SettingFieldString::set(const String & x)
|
||||
{
|
||||
value = x;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
void SettingFieldString::set(const Field & x)
|
||||
{
|
||||
set(safeGet<const String &>(x));
|
||||
}
|
||||
|
||||
void SettingFieldString::writeBinary(WriteBuffer & out) const
|
||||
{
|
||||
writeStringBinary(value, out);
|
||||
}
|
||||
|
||||
void SettingFieldString::readBinary(ReadBuffer & in)
|
||||
{
|
||||
String s;
|
||||
readStringBinary(s, in);
|
||||
set(s);
|
||||
}
|
||||
|
||||
|
||||
String SettingFieldChar::toString() const
|
||||
{
|
||||
return String(1, value);
|
||||
}
|
||||
|
||||
Field SettingFieldChar::toField() const
|
||||
{
|
||||
return toString();
|
||||
}
|
||||
|
||||
void SettingFieldChar::set(char x)
|
||||
{
|
||||
value = x;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
void SettingFieldChar::set(const String & x)
|
||||
{
|
||||
if (x.size() > 1)
|
||||
throw Exception("A setting's value string has to be an exactly one character long", ErrorCodes::SIZE_OF_FIXED_STRING_DOESNT_MATCH);
|
||||
char c = (x.size() == 1) ? x[0] : '\0';
|
||||
set(c);
|
||||
}
|
||||
|
||||
void SettingFieldChar::set(const Field & x)
|
||||
{
|
||||
const String & s = safeGet<const String &>(x);
|
||||
set(s);
|
||||
}
|
||||
|
||||
void SettingFieldChar::writeBinary(WriteBuffer & out) const
|
||||
{
|
||||
writeStringBinary(toString(), out);
|
||||
}
|
||||
|
||||
void SettingFieldChar::readBinary(ReadBuffer & in)
|
||||
{
|
||||
String s;
|
||||
readStringBinary(s, in);
|
||||
set(s);
|
||||
}
|
||||
|
||||
|
||||
String SettingFieldURI::toString() const
|
||||
{
|
||||
return value.toString();
|
||||
}
|
||||
|
||||
Field SettingFieldURI::toField() const
|
||||
{
|
||||
return value.toString();
|
||||
}
|
||||
|
||||
void SettingFieldURI::set(const Poco::URI & x)
|
||||
{
|
||||
value = x;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
void SettingFieldURI::set(const Field & x)
|
||||
{
|
||||
const String & s = safeGet<const String &>(x);
|
||||
set(s);
|
||||
}
|
||||
|
||||
void SettingFieldURI::set(const String & x)
|
||||
{
|
||||
set(Poco::URI(x));
|
||||
}
|
||||
|
||||
void SettingFieldURI::writeBinary(WriteBuffer & buf) const
|
||||
{
|
||||
writeStringBinary(toString(), buf);
|
||||
}
|
||||
|
||||
void SettingFieldURI::readBinary(ReadBuffer & buf)
|
||||
{
|
||||
String s;
|
||||
readStringBinary(s, buf);
|
||||
set(s);
|
||||
}
|
||||
|
||||
|
||||
void SettingFieldEnumHelpers::writeBinary(const std::string_view & str, WriteBuffer & out)
|
||||
{
|
||||
writeStringBinary(str, out);
|
||||
}
|
||||
|
||||
String SettingFieldEnumHelpers::readBinary(ReadBuffer & in)
|
||||
{
|
||||
String str;
|
||||
readStringBinary(str, in);
|
||||
return str;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,313 @@
|
|||
#pragma once
|
||||
|
||||
#include <Poco/Timespan.h>
|
||||
#include <Poco/URI.h>
|
||||
#include <Core/Types.h>
|
||||
#include <Core/Field.h>
|
||||
#include <boost/range/adaptor/map.hpp>
|
||||
#include <chrono>
|
||||
#include <unordered_map>
|
||||
|
||||
|
||||
namespace DB
|
||||
{
|
||||
namespace ErrorCodes
|
||||
{
|
||||
extern const int BAD_ARGUMENTS;
|
||||
}
|
||||
|
||||
class ReadBuffer;
|
||||
class WriteBuffer;
|
||||
|
||||
|
||||
/** One setting for any type.
|
||||
* Stores a value within itself, as well as a flag - whether the value was changed.
|
||||
* This is done so that you can send to the remote servers only changed settings (or explicitly specified in the config) values.
|
||||
* That is, if the configuration was not specified in the config and was not dynamically changed, it is not sent to the remote server,
|
||||
* and the remote server will use its default value.
|
||||
*/
|
||||
|
||||
template <typename Type>
|
||||
struct SettingFieldNumber
|
||||
{
|
||||
Type value;
|
||||
bool changed = false;
|
||||
|
||||
SettingFieldNumber(Type x = 0) : value(x) {}
|
||||
|
||||
operator Type() const { return value; }
|
||||
SettingFieldNumber & operator=(Type x) { set(x); return *this; }
|
||||
|
||||
/// Serialize to a test string.
|
||||
String toString() const;
|
||||
|
||||
/// Converts to a field.
|
||||
Field toField() const;
|
||||
|
||||
void set(Type x);
|
||||
|
||||
/// Read from SQL literal.
|
||||
void set(const Field & x);
|
||||
|
||||
/// Read from text string.
|
||||
void set(const String & x);
|
||||
|
||||
/// Serialize to binary stream.
|
||||
void writeBinary(WriteBuffer & out) const;
|
||||
void readBinary(ReadBuffer & in);
|
||||
};
|
||||
|
||||
using SettingFieldUInt64 = SettingFieldNumber<UInt64>;
|
||||
using SettingFieldInt64 = SettingFieldNumber<Int64>;
|
||||
using SettingFieldFloat = SettingFieldNumber<float>;
|
||||
using SettingFieldBool = SettingFieldNumber<bool>;
|
||||
|
||||
|
||||
/** Unlike SettingFieldUInt64, supports the value of 'auto' - the number of processor cores without taking into account SMT.
|
||||
* A value of 0 is also treated as auto.
|
||||
* When serializing, `auto` is written in the same way as 0.
|
||||
*/
|
||||
struct SettingFieldMaxThreads
|
||||
{
|
||||
UInt64 value;
|
||||
bool is_auto;
|
||||
bool changed = false;
|
||||
|
||||
SettingFieldMaxThreads(UInt64 x = 0) : value(x ? x : getAutoValue()), is_auto(x == 0) {}
|
||||
|
||||
operator UInt64() const { return value; }
|
||||
SettingFieldMaxThreads & operator=(UInt64 x) { set(x); return *this; }
|
||||
|
||||
String toString() const;
|
||||
Field toField() const;
|
||||
|
||||
void set(UInt64 x);
|
||||
void set(const Field & x);
|
||||
void set(const String & x);
|
||||
|
||||
void setAuto();
|
||||
static UInt64 getAutoValue();
|
||||
|
||||
void writeBinary(WriteBuffer & out) const;
|
||||
void readBinary(ReadBuffer & in);
|
||||
};
|
||||
|
||||
|
||||
enum class SettingFieldTimespanUnit { MILLISECOND, SECOND };
|
||||
|
||||
template <SettingFieldTimespanUnit unit>
|
||||
struct SettingFieldTimespan
|
||||
{
|
||||
static constexpr UInt64 microseconds_per_unit = (unit == SettingFieldTimespanUnit::MILLISECOND) ? 1000 : 1000000;
|
||||
|
||||
Poco::Timespan value;
|
||||
bool changed = false;
|
||||
|
||||
SettingFieldTimespan(UInt64 x = 0) : value(x * microseconds_per_unit) {}
|
||||
|
||||
operator Poco::Timespan() const { return value; }
|
||||
SettingFieldTimespan & operator=(const Poco::Timespan & x) { set(x); return *this; }
|
||||
|
||||
template <class Rep, class Period = std::ratio<1>>
|
||||
operator std::chrono::duration<Rep, Period>() const { return std::chrono::duration_cast<std::chrono::duration<Rep, Period>>(std::chrono::microseconds(value.totalMicroseconds())); }
|
||||
|
||||
template <class Rep, class Period = std::ratio<1>>
|
||||
SettingFieldTimespan & operator=(const std::chrono::duration<Rep, Period> & x) { set(x); return *this; }
|
||||
|
||||
Poco::Timespan::TimeDiff totalSeconds() const { return value.totalSeconds(); }
|
||||
Poco::Timespan::TimeDiff totalMilliseconds() const { return value.totalMilliseconds(); }
|
||||
|
||||
String toString() const;
|
||||
Field toField() const;
|
||||
|
||||
void set(const Poco::Timespan & x);
|
||||
|
||||
template <class Rep, class Period = std::ratio<1>>
|
||||
void set(const std::chrono::duration<Rep, Period> & duration) { set(static_cast<UInt64>(std::chrono::duration_cast<std::chrono::microseconds>(duration).count())); }
|
||||
|
||||
void set(UInt64 x);
|
||||
void set(const Field & x);
|
||||
void set(const String & x);
|
||||
|
||||
void writeBinary(WriteBuffer & out) const;
|
||||
void readBinary(ReadBuffer & in);
|
||||
};
|
||||
|
||||
using SettingFieldSeconds = SettingFieldTimespan<SettingFieldTimespanUnit::SECOND>;
|
||||
using SettingFieldMilliseconds = SettingFieldTimespan<SettingFieldTimespanUnit::MILLISECOND>;
|
||||
|
||||
|
||||
struct SettingFieldString
|
||||
{
|
||||
String value;
|
||||
bool changed = false;
|
||||
|
||||
SettingFieldString(const String & x = String{}) : value(x) {}
|
||||
|
||||
operator String() const { return value; }
|
||||
SettingFieldString & operator=(const String & x) { set(x); return *this; }
|
||||
|
||||
const String & toString() const { return value; }
|
||||
Field toField() const;
|
||||
|
||||
void set(const String & x);
|
||||
void set(const Field & x);
|
||||
|
||||
void writeBinary(WriteBuffer & out) const;
|
||||
void readBinary(ReadBuffer & in);
|
||||
};
|
||||
|
||||
|
||||
struct SettingFieldChar
|
||||
{
|
||||
public:
|
||||
char value;
|
||||
bool changed = false;
|
||||
SettingFieldChar(char x = '\0') : value(x) {}
|
||||
|
||||
operator char() const { return value; }
|
||||
SettingFieldChar & operator=(char x) { set(x); return *this; }
|
||||
|
||||
String toString() const;
|
||||
Field toField() const;
|
||||
|
||||
void set(char x);
|
||||
void set(const String & x);
|
||||
void set(const Field & x);
|
||||
|
||||
void writeBinary(WriteBuffer & out) const;
|
||||
void readBinary(ReadBuffer & in);
|
||||
};
|
||||
|
||||
|
||||
struct SettingFieldURI
|
||||
{
|
||||
Poco::URI value;
|
||||
bool changed = false;
|
||||
|
||||
SettingFieldURI(const Poco::URI & x = Poco::URI{}) : value(x) {}
|
||||
|
||||
operator Poco::URI() const { return value; }
|
||||
SettingFieldURI & operator=(const Poco::URI & x) { set(x); return *this; }
|
||||
|
||||
String toString() const;
|
||||
Field toField() const;
|
||||
|
||||
void set(const Poco::URI & x);
|
||||
void set(const Field & x);
|
||||
void set(const String & x);
|
||||
|
||||
void writeBinary(WriteBuffer & out) const;
|
||||
void readBinary(ReadBuffer & in);
|
||||
};
|
||||
|
||||
|
||||
/** Template class to define enum-based settings.
|
||||
* Example of usage:
|
||||
*
|
||||
* mysettings.h:
|
||||
* enum Gender { Male, Female };
|
||||
* DECLARE_SETTING_ENUM(SettingFieldGender, Gender)
|
||||
*
|
||||
* mysettings.cpp:
|
||||
* IMPLEMENT_SETTING_ENUM(SettingFieldGender, ErrorCodes::BAD_ARGUMENTS,
|
||||
* {{"Male", Gender::Male}, {"Female", Gender::Female}})
|
||||
*/
|
||||
template <typename EnumType, typename NameValueConverter>
|
||||
struct SettingFieldEnum
|
||||
{
|
||||
EnumType value;
|
||||
bool changed = false;
|
||||
|
||||
SettingFieldEnum(EnumType x) : value(x) {}
|
||||
|
||||
operator EnumType() const { return value; }
|
||||
SettingFieldEnum & operator=(EnumType x) { set(x); return *this; }
|
||||
|
||||
const String & toString() const { return NameValueConverter::toString(value); }
|
||||
Field toField() const { return toString(); }
|
||||
|
||||
void set(EnumType x) { value = x; changed = true; }
|
||||
void set(const Field & x) { set(safeGet<const String &>(x)); }
|
||||
void set(const String & x) { set(NameValueConverter::fromString(x)); }
|
||||
|
||||
void writeBinary(WriteBuffer & out) const;
|
||||
void readBinary(ReadBuffer & in);
|
||||
};
|
||||
|
||||
struct SettingFieldEnumHelpers
|
||||
{
|
||||
static void writeBinary(const std::string_view & str, WriteBuffer & out);
|
||||
static String readBinary(ReadBuffer & in);
|
||||
};
|
||||
|
||||
template <typename EnumType, typename NameValueConverter>
|
||||
inline void SettingFieldEnum<EnumType, NameValueConverter>::writeBinary(WriteBuffer & out) const
|
||||
{
|
||||
SettingFieldEnumHelpers::writeBinary(toString(), out);
|
||||
}
|
||||
|
||||
template <typename EnumType, typename NameValueConverter>
|
||||
inline void SettingFieldEnum<EnumType, NameValueConverter>::readBinary(ReadBuffer & in)
|
||||
{
|
||||
set(SettingFieldEnumHelpers::readBinary(in));
|
||||
}
|
||||
|
||||
#define DECLARE_SETTING_ENUM(ENUM_TYPE) \
|
||||
DECLARE_SETTING_ENUM_WITH_RENAME(ENUM_TYPE, ENUM_TYPE)
|
||||
|
||||
#define IMPLEMENT_SETTING_ENUM(ENUM_TYPE, ERROR_CODE_FOR_UNEXPECTED_NAME, ...) \
|
||||
IMPLEMENT_SETTING_ENUM_WITH_RENAME(ENUM_TYPE, ERROR_CODE_FOR_UNEXPECTED_NAME, __VA_ARGS__)
|
||||
|
||||
#define DECLARE_SETTING_ENUM_WITH_RENAME(NEW_NAME, ENUM_TYPE) \
|
||||
struct SettingField##NEW_NAME##NameValueConverter \
|
||||
{ \
|
||||
using EnumType = ENUM_TYPE; \
|
||||
static const String & toString(EnumType value); \
|
||||
static EnumType fromString(const std::string_view & str); \
|
||||
}; \
|
||||
\
|
||||
using SettingField##NEW_NAME = SettingFieldEnum<ENUM_TYPE, SettingField##NEW_NAME##NameValueConverter>;
|
||||
|
||||
#define IMPLEMENT_SETTING_ENUM_WITH_RENAME(NEW_NAME, ERROR_CODE_FOR_UNEXPECTED_NAME, ...) \
|
||||
const String & SettingField##NEW_NAME##NameValueConverter::toString(typename SettingField##NEW_NAME##NameValueConverter::EnumType value) \
|
||||
{ \
|
||||
static const std::unordered_map<EnumType, String> map = [] { \
|
||||
std::unordered_map<EnumType, String> res; \
|
||||
constexpr std::pair<const char *, EnumType> pairs[] = __VA_ARGS__; \
|
||||
for (const auto & [name, val] : pairs) \
|
||||
res.emplace(val, name); \
|
||||
return res; \
|
||||
}(); \
|
||||
auto it = map.find(value); \
|
||||
if (it != map.end()) \
|
||||
return it->second; \
|
||||
throw Exception( \
|
||||
"Unexpected value of " #NEW_NAME ":" + std::to_string(std::underlying_type<EnumType>::type(value)), \
|
||||
ERROR_CODE_FOR_UNEXPECTED_NAME); \
|
||||
} \
|
||||
\
|
||||
typename SettingField##NEW_NAME##NameValueConverter::EnumType SettingField##NEW_NAME##NameValueConverter::fromString(const std::string_view & str) \
|
||||
{ \
|
||||
static const std::unordered_map<std::string_view, EnumType> map = [] { \
|
||||
std::unordered_map<std::string_view, EnumType> res; \
|
||||
constexpr std::pair<const char *, EnumType> pairs[] = __VA_ARGS__; \
|
||||
for (const auto & [name, val] : pairs) \
|
||||
res.emplace(name, val); \
|
||||
return res; \
|
||||
}(); \
|
||||
auto it = map.find(str); \
|
||||
if (it != map.end()) \
|
||||
return it->second; \
|
||||
String msg = "Unexpected value of " #NEW_NAME ": '" + String{str} + "'. Must be one of ["; \
|
||||
bool need_comma = false; \
|
||||
for (auto & name : map | boost::adaptors::map_keys) \
|
||||
{ \
|
||||
if (std::exchange(need_comma, true)) \
|
||||
msg += ", "; \
|
||||
msg += "'" + String{name} + "'"; \
|
||||
} \
|
||||
msg += "]"; \
|
||||
throw Exception(msg, ERROR_CODE_FOR_UNEXPECTED_NAME); \
|
||||
}
|
||||
}
|
|
@ -5,7 +5,7 @@
|
|||
#include <cstddef>
|
||||
#include <string>
|
||||
#include <Core/Field.h>
|
||||
#include <Core/SettingsCollection.h>
|
||||
#include <Core/SettingsEnums.h>
|
||||
|
||||
class Collator;
|
||||
|
||||
|
|
|
@ -20,6 +20,8 @@ SRCS(
|
|||
NamesAndTypes.cpp
|
||||
Settings.cpp
|
||||
SettingsCollection.cpp
|
||||
SettingsEnums.cpp
|
||||
SettingsFields.cpp
|
||||
SortDescription.cpp
|
||||
)
|
||||
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
#include <Interpreters/SystemLog.h>
|
||||
#include <Interpreters/ClientInfo.h>
|
||||
#include <Core/SettingsCollection.h>
|
||||
|
||||
|
||||
namespace ProfileEvents
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
#include <Core/Names.h>
|
||||
#include <Core/NamesAndTypes.h>
|
||||
#include <Core/SettingsCollection.h>
|
||||
#include <Core/SettingsEnums.h>
|
||||
#include <Parsers/ASTTablesInSelectQuery.h>
|
||||
#include <Interpreters/IJoin.h>
|
||||
#include <Interpreters/asof.h>
|
||||
|
|
Loading…
Reference in New Issue