2020-07-16 22:01:08 +00:00
|
|
|
#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>
|
2020-07-27 14:26:18 +00:00
|
|
|
#include <boost/algorithm/string/predicate.hpp>
|
2020-07-16 22:01:08 +00:00
|
|
|
|
|
|
|
|
|
|
|
namespace DB
|
|
|
|
{
|
|
|
|
namespace ErrorCodes
|
|
|
|
{
|
|
|
|
extern const int SIZE_OF_FIXED_STRING_DOESNT_MATCH;
|
|
|
|
extern const int CANNOT_PARSE_BOOL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-07-27 14:26:18 +00:00
|
|
|
namespace
|
2020-07-16 22:01:08 +00:00
|
|
|
{
|
2020-07-27 14:26:18 +00:00
|
|
|
template <typename T>
|
|
|
|
T stringToNumber(const String & str)
|
|
|
|
{
|
|
|
|
if constexpr (std::is_same_v<T, bool>)
|
|
|
|
{
|
|
|
|
if (str == "0")
|
|
|
|
return false;
|
|
|
|
if (str == "1")
|
|
|
|
return true;
|
|
|
|
if (boost::iequals(str, "false"))
|
|
|
|
return false;
|
|
|
|
if (boost::iequals(str, "true"))
|
|
|
|
return true;
|
|
|
|
throw Exception("Cannot parse bool from string '" + str + "'", ErrorCodes::CANNOT_PARSE_BOOL);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return parseWithSizeSuffix<T>(str);
|
|
|
|
}
|
2020-07-16 22:01:08 +00:00
|
|
|
|
2020-07-27 14:26:18 +00:00
|
|
|
template <typename T>
|
|
|
|
T fieldToNumber(const Field & f)
|
|
|
|
{
|
|
|
|
if (f.getType() == Field::Types::String)
|
|
|
|
return stringToNumber<T>(f.get<const String &>());
|
|
|
|
else
|
|
|
|
return applyVisitor(FieldVisitorConvertToNumber<T>(), f);
|
|
|
|
}
|
2020-07-16 22:01:08 +00:00
|
|
|
}
|
|
|
|
|
2020-07-27 14:26:18 +00:00
|
|
|
template <typename T>
|
|
|
|
SettingFieldNumber<T>::SettingFieldNumber(const Field & f) : SettingFieldNumber(fieldToNumber<T>(f))
|
2020-07-16 22:01:08 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2020-07-27 14:26:18 +00:00
|
|
|
template <typename T>
|
|
|
|
SettingFieldNumber<T> & SettingFieldNumber<T>::operator=(const Field & f)
|
2020-07-16 22:01:08 +00:00
|
|
|
{
|
2020-07-27 14:26:18 +00:00
|
|
|
*this = fieldToNumber<T>(f);
|
|
|
|
return *this;
|
2020-07-16 22:01:08 +00:00
|
|
|
}
|
|
|
|
|
2020-07-27 14:26:18 +00:00
|
|
|
template <typename T>
|
|
|
|
String SettingFieldNumber<T>::toString() const
|
2020-07-16 22:01:08 +00:00
|
|
|
{
|
2020-07-27 14:26:18 +00:00
|
|
|
return ::DB::toString(value);
|
2020-07-16 22:01:08 +00:00
|
|
|
}
|
|
|
|
|
2020-07-27 14:26:18 +00:00
|
|
|
template <typename T>
|
|
|
|
void SettingFieldNumber<T>::parseFromString(const String & str)
|
2020-07-16 22:01:08 +00:00
|
|
|
{
|
2020-07-27 14:26:18 +00:00
|
|
|
*this = stringToNumber<T>(str);
|
2020-07-16 22:01:08 +00:00
|
|
|
}
|
|
|
|
|
2020-07-27 14:26:18 +00:00
|
|
|
template <typename T>
|
|
|
|
void SettingFieldNumber<T>::writeBinary(WriteBuffer & out) const
|
2020-07-16 22:01:08 +00:00
|
|
|
{
|
2020-08-19 11:52:17 +00:00
|
|
|
if constexpr (std::is_integral_v<T> && is_unsigned_v<T>)
|
2020-07-16 22:01:08 +00:00
|
|
|
writeVarUInt(static_cast<UInt64>(value), out);
|
2020-08-19 11:52:17 +00:00
|
|
|
else if constexpr (std::is_integral_v<T> && is_signed_v<T>)
|
2020-07-16 22:01:08 +00:00
|
|
|
writeVarInt(static_cast<Int64>(value), out);
|
|
|
|
else
|
|
|
|
{
|
2020-07-27 14:26:18 +00:00
|
|
|
static_assert(std::is_floating_point_v<T>);
|
|
|
|
writeStringBinary(::DB::toString(value), out);
|
2020-07-16 22:01:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-27 14:26:18 +00:00
|
|
|
template <typename T>
|
|
|
|
void SettingFieldNumber<T>::readBinary(ReadBuffer & in)
|
2020-07-16 22:01:08 +00:00
|
|
|
{
|
2020-08-19 11:52:17 +00:00
|
|
|
if constexpr (std::is_integral_v<T> && is_unsigned_v<T>)
|
2020-07-16 22:01:08 +00:00
|
|
|
{
|
|
|
|
UInt64 x;
|
|
|
|
readVarUInt(x, in);
|
2020-07-27 14:26:18 +00:00
|
|
|
*this = static_cast<T>(x);
|
2020-07-16 22:01:08 +00:00
|
|
|
}
|
2020-08-19 11:52:17 +00:00
|
|
|
else if constexpr (std::is_integral_v<T> && is_signed_v<T>)
|
2020-07-16 22:01:08 +00:00
|
|
|
{
|
|
|
|
Int64 x;
|
|
|
|
readVarInt(x, in);
|
2020-07-27 14:26:18 +00:00
|
|
|
*this = static_cast<T>(value);
|
2020-07-16 22:01:08 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-07-27 14:26:18 +00:00
|
|
|
static_assert(std::is_floating_point_v<T>);
|
|
|
|
String str;
|
|
|
|
readStringBinary(str, in);
|
|
|
|
*this = ::DB::parseFromString<T>(str);
|
2020-07-16 22:01:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
template struct SettingFieldNumber<UInt64>;
|
|
|
|
template struct SettingFieldNumber<Int64>;
|
|
|
|
template struct SettingFieldNumber<float>;
|
|
|
|
template struct SettingFieldNumber<bool>;
|
|
|
|
|
|
|
|
|
2020-07-27 14:26:18 +00:00
|
|
|
namespace
|
2020-07-16 22:01:08 +00:00
|
|
|
{
|
2020-07-27 14:26:18 +00:00
|
|
|
UInt64 stringToMaxThreads(const String & str)
|
|
|
|
{
|
|
|
|
if (startsWith(str, "auto"))
|
|
|
|
return 0;
|
|
|
|
return parseFromString<UInt64>(str);
|
|
|
|
}
|
2020-07-16 22:01:08 +00:00
|
|
|
|
2020-07-27 14:26:18 +00:00
|
|
|
UInt64 fieldToMaxThreads(const Field & f)
|
|
|
|
{
|
|
|
|
if (f.getType() == Field::Types::String)
|
|
|
|
return stringToMaxThreads(f.get<const String &>());
|
|
|
|
else
|
|
|
|
return applyVisitor(FieldVisitorConvertToNumber<UInt64>(), f);
|
|
|
|
}
|
2020-07-16 22:01:08 +00:00
|
|
|
}
|
|
|
|
|
2020-07-27 14:26:18 +00:00
|
|
|
SettingFieldMaxThreads::SettingFieldMaxThreads(const Field & f) : SettingFieldMaxThreads(fieldToMaxThreads(f))
|
2020-07-16 22:01:08 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2020-07-27 14:26:18 +00:00
|
|
|
SettingFieldMaxThreads & SettingFieldMaxThreads::operator=(const Field & f)
|
2020-07-16 22:01:08 +00:00
|
|
|
{
|
2020-07-27 14:26:18 +00:00
|
|
|
*this = fieldToMaxThreads(f);
|
|
|
|
return *this;
|
2020-07-16 22:01:08 +00:00
|
|
|
}
|
|
|
|
|
2020-07-27 14:26:18 +00:00
|
|
|
String SettingFieldMaxThreads::toString() const
|
2020-07-16 22:01:08 +00:00
|
|
|
{
|
2020-07-27 14:26:18 +00:00
|
|
|
if (is_auto)
|
|
|
|
return "'auto(" + ::DB::toString(value) + ")'";
|
2020-07-16 22:01:08 +00:00
|
|
|
else
|
2020-07-27 14:26:18 +00:00
|
|
|
return ::DB::toString(value);
|
2020-07-16 22:01:08 +00:00
|
|
|
}
|
|
|
|
|
2020-07-27 14:26:18 +00:00
|
|
|
void SettingFieldMaxThreads::parseFromString(const String & str)
|
2020-07-16 22:01:08 +00:00
|
|
|
{
|
2020-07-27 14:26:18 +00:00
|
|
|
*this = stringToMaxThreads(str);
|
2020-07-16 22:01:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void SettingFieldMaxThreads::writeBinary(WriteBuffer & out) const
|
|
|
|
{
|
|
|
|
writeVarUInt(is_auto ? 0 : value, out);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SettingFieldMaxThreads::readBinary(ReadBuffer & in)
|
|
|
|
{
|
|
|
|
UInt64 x = 0;
|
|
|
|
readVarUInt(x, in);
|
2020-07-27 14:26:18 +00:00
|
|
|
*this = x;
|
2020-07-16 22:01:08 +00:00
|
|
|
}
|
|
|
|
|
2020-07-27 14:26:18 +00:00
|
|
|
UInt64 SettingFieldMaxThreads::getAuto()
|
2020-07-16 22:01:08 +00:00
|
|
|
{
|
2020-07-27 14:26:18 +00:00
|
|
|
return getNumberOfPhysicalCPUCores();
|
2020-07-16 22:01:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-07-27 14:26:18 +00:00
|
|
|
template <SettingFieldTimespanUnit unit_>
|
|
|
|
SettingFieldTimespan<unit_>::SettingFieldTimespan(const Field & f) : SettingFieldTimespan(fieldToNumber<UInt64>(f))
|
2020-07-16 22:01:08 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2020-07-27 14:26:18 +00:00
|
|
|
template <SettingFieldTimespanUnit unit_>
|
|
|
|
SettingFieldTimespan<unit_> & SettingFieldTimespan<unit_>::operator=(const Field & f)
|
2020-07-16 22:01:08 +00:00
|
|
|
{
|
2020-07-27 14:26:18 +00:00
|
|
|
*this = fieldToNumber<UInt64>(f);
|
|
|
|
return *this;
|
2020-07-16 22:01:08 +00:00
|
|
|
}
|
|
|
|
|
2020-07-27 14:26:18 +00:00
|
|
|
template <SettingFieldTimespanUnit unit_>
|
|
|
|
String SettingFieldTimespan<unit_>::toString() const
|
2020-07-16 22:01:08 +00:00
|
|
|
{
|
2020-07-27 14:26:18 +00:00
|
|
|
return ::DB::toString(operator UInt64());
|
2020-07-16 22:01:08 +00:00
|
|
|
}
|
|
|
|
|
2020-07-27 14:26:18 +00:00
|
|
|
template <SettingFieldTimespanUnit unit_>
|
|
|
|
void SettingFieldTimespan<unit_>::parseFromString(const String & str)
|
2020-07-16 22:01:08 +00:00
|
|
|
{
|
2020-07-27 14:26:18 +00:00
|
|
|
*this = stringToNumber<UInt64>(str);
|
2020-07-16 22:01:08 +00:00
|
|
|
}
|
|
|
|
|
2020-07-27 14:26:18 +00:00
|
|
|
template <SettingFieldTimespanUnit unit_>
|
|
|
|
void SettingFieldTimespan<unit_>::writeBinary(WriteBuffer & out) const
|
2020-07-16 22:01:08 +00:00
|
|
|
{
|
2020-07-27 14:26:18 +00:00
|
|
|
auto num_units = operator UInt64();
|
|
|
|
writeVarUInt(num_units, out);
|
2020-07-16 22:01:08 +00:00
|
|
|
}
|
|
|
|
|
2020-07-27 14:26:18 +00:00
|
|
|
template <SettingFieldTimespanUnit unit_>
|
|
|
|
void SettingFieldTimespan<unit_>::readBinary(ReadBuffer & in)
|
2020-07-16 22:01:08 +00:00
|
|
|
{
|
2020-07-27 14:26:18 +00:00
|
|
|
UInt64 num_units = 0;
|
|
|
|
readVarUInt(num_units, in);
|
|
|
|
*this = num_units;
|
2020-07-16 22:01:08 +00:00
|
|
|
}
|
|
|
|
|
2020-07-27 14:26:18 +00:00
|
|
|
template struct SettingFieldTimespan<SettingFieldTimespanUnit::Second>;
|
|
|
|
template struct SettingFieldTimespan<SettingFieldTimespanUnit::Millisecond>;
|
2020-07-16 22:01:08 +00:00
|
|
|
|
|
|
|
|
|
|
|
void SettingFieldString::writeBinary(WriteBuffer & out) const
|
|
|
|
{
|
|
|
|
writeStringBinary(value, out);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SettingFieldString::readBinary(ReadBuffer & in)
|
|
|
|
{
|
2020-07-27 14:26:18 +00:00
|
|
|
String str;
|
|
|
|
readStringBinary(str, in);
|
|
|
|
*this = std::move(str);
|
2020-07-16 22:01:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-07-27 14:26:18 +00:00
|
|
|
namespace
|
2020-07-16 22:01:08 +00:00
|
|
|
{
|
2020-07-27 14:26:18 +00:00
|
|
|
char stringToChar(const String & str)
|
|
|
|
{
|
|
|
|
if (str.size() > 1)
|
|
|
|
throw Exception("A setting's value string has to be an exactly one character long", ErrorCodes::SIZE_OF_FIXED_STRING_DOESNT_MATCH);
|
|
|
|
if (str.empty())
|
|
|
|
return '\0';
|
|
|
|
return str[0];
|
|
|
|
}
|
2020-07-16 22:01:08 +00:00
|
|
|
|
2020-07-27 14:26:18 +00:00
|
|
|
char fieldToChar(const Field & f)
|
|
|
|
{
|
|
|
|
return stringToChar(f.safeGet<const String &>());
|
|
|
|
}
|
2020-07-16 22:01:08 +00:00
|
|
|
}
|
|
|
|
|
2020-07-27 14:26:18 +00:00
|
|
|
SettingFieldChar::SettingFieldChar(const Field & f) : SettingFieldChar(fieldToChar(f))
|
2020-07-16 22:01:08 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2020-07-27 14:26:18 +00:00
|
|
|
SettingFieldChar & SettingFieldChar::operator =(const Field & f)
|
2020-07-16 22:01:08 +00:00
|
|
|
{
|
2020-07-27 14:26:18 +00:00
|
|
|
*this = fieldToChar(f);
|
|
|
|
return *this;
|
2020-07-16 22:01:08 +00:00
|
|
|
}
|
|
|
|
|
2020-07-27 14:26:18 +00:00
|
|
|
void SettingFieldChar::parseFromString(const String & str)
|
2020-07-16 22:01:08 +00:00
|
|
|
{
|
2020-07-27 14:26:18 +00:00
|
|
|
*this = stringToChar(str);
|
2020-07-16 22:01:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void SettingFieldChar::writeBinary(WriteBuffer & out) const
|
|
|
|
{
|
|
|
|
writeStringBinary(toString(), out);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SettingFieldChar::readBinary(ReadBuffer & in)
|
|
|
|
{
|
2020-07-27 14:26:18 +00:00
|
|
|
String str;
|
|
|
|
readStringBinary(str, in);
|
|
|
|
*this = stringToChar(str);
|
2020-07-16 22:01:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-07-27 14:26:18 +00:00
|
|
|
void SettingFieldURI::writeBinary(WriteBuffer & out) const
|
2020-07-16 22:01:08 +00:00
|
|
|
{
|
2020-07-27 14:26:18 +00:00
|
|
|
writeStringBinary(value.toString(), out);
|
2020-07-16 22:01:08 +00:00
|
|
|
}
|
|
|
|
|
2020-07-27 14:26:18 +00:00
|
|
|
void SettingFieldURI::readBinary(ReadBuffer & in)
|
2020-07-16 22:01:08 +00:00
|
|
|
{
|
2020-07-27 14:26:18 +00:00
|
|
|
String str;
|
|
|
|
readStringBinary(str, in);
|
|
|
|
*this = Poco::URI{str};
|
2020-07-16 22:01:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2020-07-28 12:37:44 +00:00
|
|
|
|
|
|
|
String SettingFieldCustom::toString() const
|
|
|
|
{
|
|
|
|
return value.dump();
|
|
|
|
}
|
|
|
|
|
|
|
|
void SettingFieldCustom::parseFromString(const String & str)
|
|
|
|
{
|
|
|
|
*this = Field::restoreFromDump(str);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SettingFieldCustom::writeBinary(WriteBuffer & out) const
|
|
|
|
{
|
|
|
|
writeStringBinary(toString(), out);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SettingFieldCustom::readBinary(ReadBuffer & in)
|
|
|
|
{
|
|
|
|
String str;
|
|
|
|
readStringBinary(str, in);
|
|
|
|
parseFromString(str);
|
|
|
|
}
|
|
|
|
|
2020-07-16 22:01:08 +00:00
|
|
|
}
|