From 300727afa316a01cb1685636090f6a89a9116887 Mon Sep 17 00:00:00 2001 From: Vitaly Baranov Date: Mon, 27 Jul 2020 17:26:18 +0300 Subject: [PATCH] Rework the StringField* classes and make conversion String => StringField* explicit. --- src/Access/SettingsConstraints.cpp | 8 +- src/Access/SettingsProfileElement.cpp | 6 +- src/Access/UsersConfigAccessStorage.cpp | 6 +- src/Core/Settings.h | 2 +- src/Core/SettingsCollection.h | 42 +-- src/Core/SettingsCollectionImpl.h | 41 +-- src/Core/SettingsFields.cpp | 369 ++++++++++-------------- src/Core/SettingsFields.h | 195 +++++++------ src/IO/ReadHelpers.h | 4 +- src/Storages/Kafka/StorageKafka.cpp | 6 +- src/Storages/StorageJoin.cpp | 12 +- 11 files changed, 328 insertions(+), 363 deletions(-) diff --git a/src/Access/SettingsConstraints.cpp b/src/Access/SettingsConstraints.cpp index 8ca2262f8cd..2c16f23583f 100644 --- a/src/Access/SettingsConstraints.cpp +++ b/src/Access/SettingsConstraints.cpp @@ -38,7 +38,7 @@ void SettingsConstraints::setMinValue(const StringRef & setting_name, const Fiel void SettingsConstraints::setMinValue(size_t setting_index, const Field & min_value) { - getConstraintRef(setting_index).min_value = Settings::valueToCorrespondingType(setting_index, min_value); + getConstraintRef(setting_index).min_value = Settings::castValue(setting_index, min_value); } Field SettingsConstraints::getMinValue(const StringRef & setting_name) const @@ -63,7 +63,7 @@ void SettingsConstraints::setMaxValue(const StringRef & name, const Field & max_ void SettingsConstraints::setMaxValue(size_t setting_index, const Field & max_value) { - getConstraintRef(setting_index).max_value = Settings::valueToCorrespondingType(setting_index, max_value); + getConstraintRef(setting_index).max_value = Settings::castValue(setting_index, max_value); } Field SettingsConstraints::getMaxValue(const StringRef & setting_name) const @@ -179,7 +179,7 @@ void SettingsConstraints::check(const Settings & current_settings, const Setting if (setting_index == Settings::npos) return; - Field new_value = Settings::valueToCorrespondingType(setting_index, change.value); + Field new_value = Settings::castValue(setting_index, change.value); Field current_value = current_settings.get(setting_index); /// Setting isn't checked if value wasn't changed. @@ -233,7 +233,7 @@ void SettingsConstraints::clamp(const Settings & current_settings, SettingChange if (setting_index == Settings::npos) return; - Field new_value = Settings::valueToCorrespondingType(setting_index, change.value); + Field new_value = Settings::castValue(setting_index, change.value); Field current_value = current_settings.get(setting_index); /// Setting isn't checked if value wasn't changed. diff --git a/src/Access/SettingsProfileElement.cpp b/src/Access/SettingsProfileElement.cpp index 4fbe4aec2f8..cb9b26cce53 100644 --- a/src/Access/SettingsProfileElement.cpp +++ b/src/Access/SettingsProfileElement.cpp @@ -43,11 +43,11 @@ void SettingsProfileElement::init(const ASTSettingsProfileElement & ast, const A readonly = ast.readonly; if (!value.isNull()) - value = Settings::valueToCorrespondingType(setting_index, value); + value = Settings::castValue(setting_index, value); if (!min_value.isNull()) - min_value = Settings::valueToCorrespondingType(setting_index, min_value); + min_value = Settings::castValue(setting_index, min_value); if (!max_value.isNull()) - max_value = Settings::valueToCorrespondingType(setting_index, max_value); + max_value = Settings::castValue(setting_index, max_value); } } diff --git a/src/Access/UsersConfigAccessStorage.cpp b/src/Access/UsersConfigAccessStorage.cpp index e3fb9104a66..a4a0acfc664 100644 --- a/src/Access/UsersConfigAccessStorage.cpp +++ b/src/Access/UsersConfigAccessStorage.cpp @@ -375,9 +375,9 @@ namespace for (const String & constraint_type : constraint_types) { if (constraint_type == "min") - profile_element.min_value = Settings::valueToCorrespondingType(setting_index, config.getString(path_to_name + "." + constraint_type)); + profile_element.min_value = Settings::stringToValue(setting_index, config.getString(path_to_name + "." + constraint_type)); else if (constraint_type == "max") - profile_element.max_value = Settings::valueToCorrespondingType(setting_index, config.getString(path_to_name + "." + constraint_type)); + profile_element.max_value = Settings::stringToValue(setting_index, config.getString(path_to_name + "." + constraint_type)); else if (constraint_type == "readonly") profile_element.readonly = true; else @@ -419,7 +419,7 @@ namespace SettingsProfileElement profile_element; size_t setting_index = Settings::findIndexStrict(key); profile_element.setting_index = setting_index; - profile_element.value = Settings::valueToCorrespondingType(setting_index, config.getString(profile_config + "." + key)); + profile_element.value = Settings::stringToValue(setting_index, config.getString(profile_config + "." + key)); profile->elements.emplace_back(std::move(profile_element)); } diff --git a/src/Core/Settings.h b/src/Core/Settings.h index 208de421b76..9cc26f9c324 100644 --- a/src/Core/Settings.h +++ b/src/Core/Settings.h @@ -433,7 +433,7 @@ struct Settings : public SettingsCollection M(Bool, input_format_values_deduce_templates_of_expressions, true, "For Values format: if the field could not be parsed by streaming parser, run SQL parser, deduce template of the SQL expression, try to parse all rows using template and then interpret expression for all rows.", 0) \ M(Bool, input_format_values_accurate_types_of_literals, true, "For Values format: when parsing and interpreting expressions using template, check actual type of literal to avoid possible overflow and precision issues.", 0) \ M(Bool, input_format_avro_allow_missing_fields, false, "For Avro/AvroConfluent format: when field is not found in schema use default value instead of error", 0) \ - M(URI, format_avro_schema_registry_url, {}, "For AvroConfluent format: Confluent Schema Registry URL.", 0) \ + M(URI, format_avro_schema_registry_url, "", "For AvroConfluent format: Confluent Schema Registry URL.", 0) \ \ M(Bool, output_format_json_quote_64bit_integers, true, "Controls quoting of 64-bit integers in JSON output format.", 0) \ \ diff --git a/src/Core/SettingsCollection.h b/src/Core/SettingsCollection.h index 5a6bef3d1d0..9b19e7ae04e 100644 --- a/src/Core/SettingsCollection.h +++ b/src/Core/SettingsCollection.h @@ -49,28 +49,30 @@ private: struct MemberInfo { using IsChangedFunction = bool (*)(const Derived &); - using GetStringFunction = String (*)(const Derived &); - using GetFieldFunction = Field (*)(const Derived &); - using SetStringFunction = void (*)(Derived &, const String &); - using SetFieldFunction = void (*)(Derived &, const Field &); + using GetValueFunction = Field (*)(const Derived &); + using SetValueFunction = void (*)(Derived &, const Field &); + using GetValueAsStringFunction = String (*)(const Derived &); + using ParseValueFromStringFunction = void (*)(Derived &, const String &); using WriteBinaryFunction = void (*)(const Derived &, WriteBuffer & buf); using ReadBinaryFunction = void (*)(Derived &, ReadBuffer & buf); + using CastValueFunction = Field (*)(const Field &); + using StringToValueFunction = Field (*)(const String &); using ValueToStringFunction = String (*)(const Field &); - using ValueToCorrespondingTypeFunction = Field (*)(const Field &); StringRef name; StringRef description; StringRef type; bool is_important; IsChangedFunction is_changed; - GetStringFunction get_string; - GetFieldFunction get_field; - SetStringFunction set_string; - SetFieldFunction set_field; + GetValueFunction get_value; + SetValueFunction set_value; + GetValueAsStringFunction get_value_as_string; + ParseValueFromStringFunction parse_value_from_string; WriteBinaryFunction write_binary; ReadBinaryFunction read_binary; + CastValueFunction cast_value; + StringToValueFunction string_to_value; ValueToStringFunction value_to_string; - ValueToCorrespondingTypeFunction value_to_corresponding_type; }; class MemberInfos @@ -110,7 +112,7 @@ public: const StringRef & getType() const { return member->type; } bool isChanged() const { return member->is_changed(*collection); } Field getValue() const; - String getValueAsString() const { return member->get_string(*collection); } + String getValueAsString() const { return member->get_value_as_string(*collection); } protected: friend class SettingsCollection::const_iterator; @@ -126,8 +128,8 @@ public: public: reference(Derived & collection_, const MemberInfo & member_) : const_reference(collection_, member_) {} reference(const const_reference & src) : const_reference(src) {} - void setValue(const Field & value) { this->member->set_field(*const_cast(this->collection), value); } - void setValue(const String & value) { this->member->set_string(*const_cast(this->collection), value); } + void setValue(const Field & value) { this->member->set_value(*const_cast(this->collection), value); } + void parseFromString(const String & value) { this->member->parse_value_from_string(*const_cast(this->collection), value); } }; /// Iterator to iterating through all the settings. @@ -178,14 +180,16 @@ public: /// Searches a setting by its name; throws an exception if not found. static size_t findIndexStrict(const StringRef & name) { return members().findIndexStrict(name); } - /// Casts a value to a string according to a specified setting without actual changing this settings. - static String valueToString(size_t index, const Field & value) { return members()[index].value_to_string(value); } - static String valueToString(const StringRef & name, const Field & value) { return members().findStrict(name).value_to_string(value); } - /// Casts a value to a type according to a specified setting without actual changing this settings. /// E.g. for SettingInt64 it casts Field to Field::Types::Int64. - static Field valueToCorrespondingType(size_t index, const Field & value); - static Field valueToCorrespondingType(const StringRef & name, const Field & value); + static Field castValue(size_t index, const Field & value); + static Field castValue(const StringRef & name, const Field & value); + + /// Casts a value to a string according to a specified setting without actual changing this settings. + static Field stringToValue(size_t index, const String & str) { return members()[index].string_to_value(str); } + static Field stringToValue(const StringRef & name, const String & str) { return members().findStrict(name).string_to_value(str); } + static String valueToString(size_t index, const Field & value) { return members()[index].value_to_string(value); } + static String valueToString(const StringRef & name, const Field & value) { return members().findStrict(name).value_to_string(value); } iterator begin() { return iterator(castToDerived(), members().data()); } const_iterator begin() const { return const_iterator(castToDerived(), members().data()); } diff --git a/src/Core/SettingsCollectionImpl.h b/src/Core/SettingsCollectionImpl.h index 913ba9f5b33..fd365b9587e 100644 --- a/src/Core/SettingsCollectionImpl.h +++ b/src/Core/SettingsCollectionImpl.h @@ -6,8 +6,10 @@ * instantiation of SettingsCollection<>. */ +#include #include #include +#include namespace DB @@ -86,16 +88,16 @@ SettingsCollection::members() template Field SettingsCollection::const_reference::getValue() const { - return member->get_field(*collection); + return member->get_value(*collection); } template -Field SettingsCollection::valueToCorrespondingType(size_t index, const Field & value) +Field SettingsCollection::castValue(size_t index, const Field & value) { try { - return members()[index].value_to_corresponding_type(value); + return members()[index].cast_value(value); } catch (Exception & e) { @@ -107,9 +109,9 @@ Field SettingsCollection::valueToCorrespondingType(size_t index, const template -Field SettingsCollection::valueToCorrespondingType(const StringRef & name, const Field & value) +Field SettingsCollection::castValue(const StringRef & name, const Field & value) { - return members().findStrict(name).value_to_corresponding_type(value); + return members().findStrict(name).cast_value(value); } @@ -196,7 +198,7 @@ bool SettingsCollection::operator ==(const SettingsCollection { if (left_changed != right_changed) return false; - if (member.get_field(castToDerived()) != member.get_field(rhs.castToDerived())) + if (member.get_value(castToDerived()) != member.get_value(rhs.castToDerived())) return false; } } @@ -213,7 +215,7 @@ SettingsChanges SettingsCollection::changes() const { const auto & member = the_members[i]; if (member.is_changed(castToDerived())) - found_changes.push_back({member.name.toString(), member.get_field(castToDerived())}); + found_changes.push_back({member.name.toString(), member.get_value(castToDerived())}); } return found_changes; } @@ -255,7 +257,7 @@ void SettingsCollection::copyChangesFrom(const Derived & src) { const auto & member = the_members[i]; if (member.is_changed(src)) - member.set_field(castToDerived(), member.get_field(src)); + member.set_value(castToDerived(), member.get_value(src)); } } @@ -280,7 +282,7 @@ void SettingsCollection::serialize(WriteBuffer & buf, SettingsBinaryFor if (format >= SettingsBinaryFormat::STRINGS) { details::SettingsCollectionUtils::serializeFlag(member.is_important, buf); - details::SettingsCollectionUtils::serializeName(member.get_string(castToDerived()), buf); + details::SettingsCollectionUtils::serializeName(member.get_value_as_string(castToDerived()), buf); } else member.write_binary(castToDerived(), buf); @@ -320,7 +322,7 @@ void SettingsCollection::deserialize(ReadBuffer & buf, SettingsBinaryFo if (format >= SettingsBinaryFormat::STRINGS) { String value = details::SettingsCollectionUtils::deserializeName(buf); - member->set_string(castToDerived(), value); + member->parse_value_from_string(castToDerived(), value); } else member->read_binary(castToDerived(), buf); @@ -350,14 +352,15 @@ void SettingsCollection::deserialize(ReadBuffer & buf, SettingsBinaryFo #define IMPLEMENT_SETTINGS_COLLECTION_DEFINE_FUNCTIONS_HELPER_(TYPE, NAME, DEFAULT, DESCRIPTION, FLAGS) \ - static String NAME##_getString(const Derived & collection) { return collection.NAME.toString(); } \ - 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 Field NAME##_getValue(const Derived & collection) { return static_cast(collection.NAME); } \ + static void NAME##_setValue(Derived & collection, const Field & value) { collection.NAME = value; } \ + static String NAME##_toString(const Derived & collection) { return collection.NAME.toString(); } \ + static void NAME##_parseFromString(Derived & collection, const String & value) { collection.NAME.parseFromString(value); } \ 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(); } \ + static Field NAME##_castValue(const Field & value) { return static_cast(SettingField##TYPE{value}); } \ + static Field NAME##_stringToValue(const String & str) { SettingField##TYPE temp; temp.parseFromString(str); return static_cast(temp); } \ + static String NAME##_valueToString(const Field & value) { return SettingField##TYPE{value}.toString(); } \ #define IMPLEMENT_SETTINGS_COLLECTION_ADD_MEMBER_INFO_HELPER_(TYPE, NAME, DEFAULT, DESCRIPTION, FLAGS) \ @@ -366,8 +369,8 @@ void SettingsCollection::deserialize(ReadBuffer & buf, SettingsBinaryFo StringRef(#TYPE, strlen(#TYPE)), \ FLAGS & IMPORTANT, \ [](const Derived & d) { return d.NAME.changed; }, \ - &Functions::NAME##_getString, &Functions::NAME##_getField, \ - &Functions::NAME##_setString, &Functions::NAME##_setField, \ + &Functions::NAME##_getValue, &Functions::NAME##_setValue, \ + &Functions::NAME##_toString, &Functions::NAME##_parseFromString, \ &Functions::NAME##_writeBinary, &Functions::NAME##_readBinary, \ - &Functions::NAME##_valueToString, &Functions::NAME##_valueToCorrespondingType}); + &Functions::NAME##_castValue, &Functions::NAME##_stringToValue, &Functions::NAME##_valueToString }); } diff --git a/src/Core/SettingsFields.cpp b/src/Core/SettingsFields.cpp index b2053a6a8c1..628e6ef6d4c 100644 --- a/src/Core/SettingsFields.cpp +++ b/src/Core/SettingsFields.cpp @@ -7,6 +7,7 @@ #include #include #include +#include namespace DB @@ -18,100 +19,96 @@ namespace ErrorCodes } -template -String SettingFieldNumber::toString() const +namespace { - return DB::toString(value); -} - -template -Field SettingFieldNumber::toField() const -{ - return value; -} - -template -void SettingFieldNumber::set(Type x) -{ - value = x; - changed = true; -} - -template -void SettingFieldNumber::set(const Field & x) -{ - if (x.getType() == Field::Types::String) - set(get(x)); - else - set(applyVisitor(FieldVisitorConvertToNumber(), x)); -} - -template -void SettingFieldNumber::set(const String & x) -{ - set(parseWithSizeSuffix(x)); -} - -template <> -void SettingFieldNumber::set(const String & x) -{ - if (x.size() == 1) + template + T stringToNumber(const String & str) { - if (x[0] == '0') - set(false); - else if (x[0] == '1') - set(true); + if constexpr (std::is_same_v) + { + 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 - throw Exception("Cannot parse bool from string '" + x + "'", ErrorCodes::CANNOT_PARSE_BOOL); + return parseWithSizeSuffix(str); } - else + + template + T fieldToNumber(const Field & f) { - ReadBufferFromString buf(x); - if (checkStringCaseInsensitive("true", buf)) - set(true); - else if (checkStringCaseInsensitive("false", buf)) - set(false); + if (f.getType() == Field::Types::String) + return stringToNumber(f.get()); else - throw Exception("Cannot parse bool from string '" + x + "'", ErrorCodes::CANNOT_PARSE_BOOL); + return applyVisitor(FieldVisitorConvertToNumber(), f); } } - -template -void SettingFieldNumber::writeBinary(WriteBuffer & out) const +template +SettingFieldNumber::SettingFieldNumber(const Field & f) : SettingFieldNumber(fieldToNumber(f)) { - if constexpr (is_integral_v && is_unsigned_v) +} + +template +SettingFieldNumber & SettingFieldNumber::operator=(const Field & f) +{ + *this = fieldToNumber(f); + return *this; +} + +template +String SettingFieldNumber::toString() const +{ + return ::DB::toString(value); +} + +template +void SettingFieldNumber::parseFromString(const String & str) +{ + *this = stringToNumber(str); +} + +template +void SettingFieldNumber::writeBinary(WriteBuffer & out) const +{ + if constexpr (is_integral_v && is_unsigned_v) writeVarUInt(static_cast(value), out); - else if constexpr (is_integral_v && is_signed_v) + else if constexpr (is_integral_v && is_signed_v) writeVarInt(static_cast(value), out); else { - static_assert(std::is_floating_point_v); - writeStringBinary(toString(), out); + static_assert(std::is_floating_point_v); + writeStringBinary(::DB::toString(value), out); } } -template -void SettingFieldNumber::readBinary(ReadBuffer & in) +template +void SettingFieldNumber::readBinary(ReadBuffer & in) { - if constexpr (is_integral_v && is_unsigned_v) + if constexpr (is_integral_v && is_unsigned_v) { UInt64 x; readVarUInt(x, in); - set(static_cast(x)); + *this = static_cast(x); } - else if constexpr (is_integral_v && is_signed_v) + else if constexpr (is_integral_v && is_signed_v) { Int64 x; readVarInt(x, in); - set(static_cast(x)); + *this = static_cast(value); } else { - static_assert(std::is_floating_point_v); - String x; - readStringBinary(x, in); - set(x); + static_assert(std::is_floating_point_v); + String str; + readStringBinary(str, in); + *this = ::DB::parseFromString(str); } } @@ -121,50 +118,45 @@ template struct SettingFieldNumber; template struct SettingFieldNumber; +namespace +{ + UInt64 stringToMaxThreads(const String & str) + { + if (startsWith(str, "auto")) + return 0; + return parseFromString(str); + } + + UInt64 fieldToMaxThreads(const Field & f) + { + if (f.getType() == Field::Types::String) + return stringToMaxThreads(f.get()); + else + return applyVisitor(FieldVisitorConvertToNumber(), f); + } +} + +SettingFieldMaxThreads::SettingFieldMaxThreads(const Field & f) : SettingFieldMaxThreads(fieldToMaxThreads(f)) +{ +} + +SettingFieldMaxThreads & SettingFieldMaxThreads::operator=(const Field & f) +{ + *this = fieldToMaxThreads(f); + return *this; +} + 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(x)); + if (is_auto) + return "'auto(" + ::DB::toString(value) + ")'"; else - set(applyVisitor(FieldVisitorConvertToNumber(), x)); + return ::DB::toString(value); } -void SettingFieldMaxThreads::set(const String & x) +void SettingFieldMaxThreads::parseFromString(const String & str) { - if (startsWith(x, "auto")) - setAuto(); - else - set(parse(x)); -} - -void SettingFieldMaxThreads::setAuto() -{ - value = getAutoValue(); - is_auto = true; -} - -UInt64 SettingFieldMaxThreads::getAutoValue() -{ - static auto res = getNumberOfPhysicalCPUCores(); - return res; + *this = stringToMaxThreads(str); } void SettingFieldMaxThreads::writeBinary(WriteBuffer & out) const @@ -176,83 +168,57 @@ void SettingFieldMaxThreads::readBinary(ReadBuffer & in) { UInt64 x = 0; readVarUInt(x, in); - set(x); + *this = x; } - -template -String SettingFieldTimespan::toString() const +UInt64 SettingFieldMaxThreads::getAuto() { - return DB::toString(value.totalMicroseconds() / microseconds_per_unit); + return getNumberOfPhysicalCPUCores(); } -template -Field SettingFieldTimespan::toField() const + +template +SettingFieldTimespan::SettingFieldTimespan(const Field & f) : SettingFieldTimespan(fieldToNumber(f)) { - return value.totalMicroseconds() / microseconds_per_unit; } -template -void SettingFieldTimespan::set(const Poco::Timespan & x) +template +SettingFieldTimespan & SettingFieldTimespan::operator=(const Field & f) { - value = x; - changed = true; + *this = fieldToNumber(f); + return *this; } -template -void SettingFieldTimespan::set(UInt64 x) +template +String SettingFieldTimespan::toString() const { - set(Poco::Timespan(x * microseconds_per_unit)); + return ::DB::toString(operator UInt64()); } -template -void SettingFieldTimespan::set(const Field & x) +template +void SettingFieldTimespan::parseFromString(const String & str) { - if (x.getType() == Field::Types::String) - set(get(x)); - else - set(applyVisitor(FieldVisitorConvertToNumber(), x)); + *this = stringToNumber(str); } -template -void SettingFieldTimespan::set(const String & x) +template +void SettingFieldTimespan::writeBinary(WriteBuffer & out) const { - set(parse(x)); + auto num_units = operator UInt64(); + writeVarUInt(num_units, out); } -template -void SettingFieldTimespan::writeBinary(WriteBuffer & out) const +template +void SettingFieldTimespan::readBinary(ReadBuffer & in) { - writeVarUInt(value.totalMicroseconds() / microseconds_per_unit, out); + UInt64 num_units = 0; + readVarUInt(num_units, in); + *this = num_units; } -template -void SettingFieldTimespan::readBinary(ReadBuffer & in) -{ - UInt64 x = 0; - readVarUInt(x, in); - set(x); -} +template struct SettingFieldTimespan; +template struct SettingFieldTimespan; -template struct SettingFieldTimespan; -template struct SettingFieldTimespan; - - -Field SettingFieldString::toField() const -{ - return value; -} - -void SettingFieldString::set(const String & x) -{ - value = x; - changed = true; -} - -void SettingFieldString::set(const Field & x) -{ - set(safeGet(x)); -} void SettingFieldString::writeBinary(WriteBuffer & out) const { @@ -261,40 +227,42 @@ void SettingFieldString::writeBinary(WriteBuffer & out) const void SettingFieldString::readBinary(ReadBuffer & in) { - String s; - readStringBinary(s, in); - set(s); + String str; + readStringBinary(str, in); + *this = std::move(str); } -String SettingFieldChar::toString() const +namespace { - return String(1, value); + 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]; + } + + char fieldToChar(const Field & f) + { + return stringToChar(f.safeGet()); + } } -Field SettingFieldChar::toField() const +SettingFieldChar::SettingFieldChar(const Field & f) : SettingFieldChar(fieldToChar(f)) { - return toString(); } -void SettingFieldChar::set(char x) +SettingFieldChar & SettingFieldChar::operator =(const Field & f) { - value = x; - changed = true; + *this = fieldToChar(f); + return *this; } -void SettingFieldChar::set(const String & x) +void SettingFieldChar::parseFromString(const String & str) { - 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(x); - set(s); + *this = stringToChar(str); } void SettingFieldChar::writeBinary(WriteBuffer & out) const @@ -304,49 +272,22 @@ void SettingFieldChar::writeBinary(WriteBuffer & out) const void SettingFieldChar::readBinary(ReadBuffer & in) { - String s; - readStringBinary(s, in); - set(s); + String str; + readStringBinary(str, in); + *this = stringToChar(str); } -String SettingFieldURI::toString() const +void SettingFieldURI::writeBinary(WriteBuffer & out) const { - return value.toString(); + writeStringBinary(value.toString(), out); } -Field SettingFieldURI::toField() const +void SettingFieldURI::readBinary(ReadBuffer & in) { - return value.toString(); -} - -void SettingFieldURI::set(const Poco::URI & x) -{ - value = x; - changed = true; -} - -void SettingFieldURI::set(const Field & x) -{ - const String & s = safeGet(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); + String str; + readStringBinary(str, in); + *this = Poco::URI{str}; } diff --git a/src/Core/SettingsFields.h b/src/Core/SettingsFields.h index a972180eaee..f6e03ab9dde 100644 --- a/src/Core/SettingsFields.h +++ b/src/Core/SettingsFields.h @@ -27,32 +27,26 @@ class WriteBuffer; * and the remote server will use its default value. */ -template +template struct SettingFieldNumber { + using Type = T; + Type value; bool changed = false; - SettingFieldNumber(Type x = 0) : value(x) {} + explicit SettingFieldNumber(Type x = 0) : value(x) {} + explicit SettingFieldNumber(const Field & f); + + SettingFieldNumber & operator=(Type x) { value = x; changed = true; return *this; } + SettingFieldNumber & operator=(const Field & f); operator Type() const { return value; } - SettingFieldNumber & operator=(Type x) { set(x); return *this; } + explicit operator Field() const { return value; } - /// Serialize to a test string. String toString() const; + void parseFromString(const String & str); - /// 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); }; @@ -69,72 +63,80 @@ using SettingFieldBool = SettingFieldNumber; */ struct SettingFieldMaxThreads { - UInt64 value; bool is_auto; + UInt64 value; bool changed = false; - SettingFieldMaxThreads(UInt64 x = 0) : value(x ? x : getAutoValue()), is_auto(x == 0) {} + explicit SettingFieldMaxThreads(UInt64 x = 0) : is_auto(!x), value(is_auto ? getAuto() : x) {} + explicit SettingFieldMaxThreads(const Field & f); + + SettingFieldMaxThreads & operator=(UInt64 x) { is_auto = !x; value = is_auto ? getAuto() : x; changed = true; return *this; } + SettingFieldMaxThreads & operator=(const Field & f); operator UInt64() const { return value; } - SettingFieldMaxThreads & operator=(UInt64 x) { set(x); return *this; } + explicit operator Field() const { return value; } + /// Writes "auto()" instead of simple "" if `is_auto==true`. 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 parseFromString(const String & str); void writeBinary(WriteBuffer & out) const; void readBinary(ReadBuffer & in); + +private: + static UInt64 getAuto(); }; -enum class SettingFieldTimespanUnit { MILLISECOND, SECOND }; +enum class SettingFieldTimespanUnit { Millisecond, Second }; -template +template struct SettingFieldTimespan { - static constexpr UInt64 microseconds_per_unit = (unit == SettingFieldTimespanUnit::MILLISECOND) ? 1000 : 1000000; - + using Unit = SettingFieldTimespanUnit; + static constexpr Unit unit = unit_; + 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) {} + explicit SettingFieldTimespan(const Poco::Timespan & x = {}) : value(x) {} + + template > + explicit SettingFieldTimespan(const std::chrono::duration & x) + : SettingFieldTimespan(Poco::Timespan{static_cast(std::chrono::duration_cast(x).count())}) {} + + explicit SettingFieldTimespan(UInt64 x) : SettingFieldTimespan(Poco::Timespan{static_cast(x * microseconds_per_unit)}) {} + explicit SettingFieldTimespan(const Field & f); + + SettingFieldTimespan & operator =(const Poco::Timespan & x) { value = x; changed = true; return *this; } + + template > + SettingFieldTimespan & operator =(const std::chrono::duration & x) { *this = Poco::Timespan{static_cast(std::chrono::duration_cast(x).count())}; return *this; } + + SettingFieldTimespan & operator =(UInt64 x) { *this = Poco::Timespan{static_cast(x * microseconds_per_unit)}; return *this; } + SettingFieldTimespan & operator =(const Field & f); operator Poco::Timespan() const { return value; } - SettingFieldTimespan & operator=(const Poco::Timespan & x) { set(x); return *this; } template > operator std::chrono::duration() const { return std::chrono::duration_cast>(std::chrono::microseconds(value.totalMicroseconds())); } - template > - SettingFieldTimespan & operator=(const std::chrono::duration & x) { set(x); return *this; } + explicit operator UInt64() const { return value.totalMicroseconds() / microseconds_per_unit; } + explicit operator Field() const { return operator UInt64(); } - Poco::Timespan::TimeDiff totalSeconds() const { return value.totalSeconds(); } + Poco::Timespan::TimeDiff totalMicroseconds() const { return value.totalMicroseconds(); } Poco::Timespan::TimeDiff totalMilliseconds() const { return value.totalMilliseconds(); } + Poco::Timespan::TimeDiff totalSeconds() const { return value.totalSeconds(); } String toString() const; - Field toField() const; - - void set(const Poco::Timespan & x); - - template > - void set(const std::chrono::duration & duration) { set(static_cast(std::chrono::duration_cast(duration).count())); } - - void set(UInt64 x); - void set(const Field & x); - void set(const String & x); + void parseFromString(const String & str); void writeBinary(WriteBuffer & out) const; void readBinary(ReadBuffer & in); }; -using SettingFieldSeconds = SettingFieldTimespan; -using SettingFieldMilliseconds = SettingFieldTimespan; +using SettingFieldSeconds = SettingFieldTimespan; +using SettingFieldMilliseconds = SettingFieldTimespan; struct SettingFieldString @@ -142,16 +144,23 @@ struct SettingFieldString String value; bool changed = false; - SettingFieldString(const String & x = String{}) : value(x) {} + explicit SettingFieldString(const std::string_view & str = {}) : value(str) {} + explicit SettingFieldString(const String & str) : SettingFieldString(std::string_view{str}) {} + explicit SettingFieldString(String && str) : value(std::move(str)) {} + explicit SettingFieldString(const char * str) : SettingFieldString(std::string_view{str}) {} + explicit SettingFieldString(const Field & f) : SettingFieldString(f.safeGet()) {} - operator String() const { return value; } - SettingFieldString & operator=(const String & x) { set(x); return *this; } + SettingFieldString & operator =(const std::string_view & str) { value = str; changed = true; return *this; } + SettingFieldString & operator =(const String & str) { *this = std::string_view{str}; return *this; } + SettingFieldString & operator =(String && str) { value = std::move(str); changed = true; return *this; } + SettingFieldString & operator =(const char * str) { *this = std::string_view{str}; return *this; } + SettingFieldString & operator =(const Field & f) { *this = f.safeGet(); return *this; } + + operator const String &() const { return value; } + explicit operator Field() const { return value; } const String & toString() const { return value; } - Field toField() const; - - void set(const String & x); - void set(const Field & x); + void parseFromString(const String & str) { *this = str; } void writeBinary(WriteBuffer & out) const; void readBinary(ReadBuffer & in); @@ -163,17 +172,18 @@ struct SettingFieldChar public: char value; bool changed = false; - SettingFieldChar(char x = '\0') : value(x) {} + + explicit SettingFieldChar(char c = '\0') : value(c) {} + explicit SettingFieldChar(const Field & f); + + SettingFieldChar & operator =(char c) { value = c; changed = true; return *this; } + SettingFieldChar & operator =(const Field & f); operator char() const { return value; } - SettingFieldChar & operator=(char x) { set(x); return *this; } + explicit operator Field() const { return toString(); } - String toString() const; - Field toField() const; - - void set(char x); - void set(const String & x); - void set(const Field & x); + String toString() const { return String(&value, 1); } + void parseFromString(const String & str); void writeBinary(WriteBuffer & out) const; void readBinary(ReadBuffer & in); @@ -185,17 +195,22 @@ struct SettingFieldURI Poco::URI value; bool changed = false; - SettingFieldURI(const Poco::URI & x = Poco::URI{}) : value(x) {} + explicit SettingFieldURI(const Poco::URI & uri = {}) : value(uri) {} + explicit SettingFieldURI(const String & str) : SettingFieldURI(Poco::URI{str}) {} + explicit SettingFieldURI(const char * str) : SettingFieldURI(Poco::URI{str}) {} + explicit SettingFieldURI(const Field & f) : SettingFieldURI(f.safeGet()) {} - operator Poco::URI() const { return value; } - SettingFieldURI & operator=(const Poco::URI & x) { set(x); return *this; } + SettingFieldURI & operator =(const Poco::URI & x) { value = x; changed = true; return *this; } + SettingFieldURI & operator =(const String & str) { *this = Poco::URI{str}; return *this; } + SettingFieldURI & operator =(const char * str) { *this = Poco::URI{str}; return *this; } + SettingFieldURI & operator =(const Field & f) { *this = f.safeGet(); return *this; } - String toString() const; - Field toField() const; + operator const Poco::URI &() const { return value; } + explicit operator String() const { return toString(); } + explicit operator Field() const { return toString(); } - void set(const Poco::URI & x); - void set(const Field & x); - void set(const String & x); + String toString() const { return value.toString(); } + void parseFromString(const String & str) { *this = str; } void writeBinary(WriteBuffer & out) const; void readBinary(ReadBuffer & in); @@ -213,23 +228,25 @@ struct SettingFieldURI * IMPLEMENT_SETTING_ENUM(SettingFieldGender, ErrorCodes::BAD_ARGUMENTS, * {{"Male", Gender::Male}, {"Female", Gender::Female}}) */ -template +template struct SettingFieldEnum { + using EnumType = EnumT; + EnumType value; bool changed = false; - SettingFieldEnum(EnumType x) : value(x) {} + explicit SettingFieldEnum(EnumType x = EnumType{0}) : value(x) {} + explicit SettingFieldEnum(const Field & f) : SettingFieldEnum(Traits::fromString(f.safeGet())) {} + + SettingFieldEnum & operator =(EnumType x) { value = x; changed = true; return *this; } + SettingFieldEnum & operator =(const Field & f) { *this = Traits::fromString(f.safeGet()); return *this; } operator EnumType() const { return value; } - SettingFieldEnum & operator=(EnumType x) { set(x); return *this; } + explicit operator Field() const { return toString(); } - 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(x)); } - void set(const String & x) { set(NameValueConverter::fromString(x)); } + String toString() const { return Traits::toString(value); } + void parseFromString(const String & str) { *this = Traits::fromString(str); } void writeBinary(WriteBuffer & out) const; void readBinary(ReadBuffer & in); @@ -241,16 +258,16 @@ struct SettingFieldEnumHelpers static String readBinary(ReadBuffer & in); }; -template -inline void SettingFieldEnum::writeBinary(WriteBuffer & out) const +template +void SettingFieldEnum::writeBinary(WriteBuffer & out) const { SettingFieldEnumHelpers::writeBinary(toString(), out); } -template -inline void SettingFieldEnum::readBinary(ReadBuffer & in) +template +void SettingFieldEnum::readBinary(ReadBuffer & in) { - set(SettingFieldEnumHelpers::readBinary(in)); + *this = Traits::fromString(SettingFieldEnumHelpers::readBinary(in)); } #define DECLARE_SETTING_ENUM(ENUM_TYPE) \ @@ -260,17 +277,17 @@ inline void SettingFieldEnum::readBinary(ReadBuffe 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 \ + struct SettingField##NEW_NAME##Traits \ { \ using EnumType = ENUM_TYPE; \ static const String & toString(EnumType value); \ static EnumType fromString(const std::string_view & str); \ }; \ \ - using SettingField##NEW_NAME = SettingFieldEnum; + using SettingField##NEW_NAME = SettingFieldEnum; #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) \ + const String & SettingField##NEW_NAME##Traits::toString(typename SettingField##NEW_NAME::EnumType value) \ { \ static const std::unordered_map map = [] { \ std::unordered_map res; \ @@ -287,7 +304,7 @@ inline void SettingFieldEnum::readBinary(ReadBuffe ERROR_CODE_FOR_UNEXPECTED_NAME); \ } \ \ - typename SettingField##NEW_NAME##NameValueConverter::EnumType SettingField##NEW_NAME##NameValueConverter::fromString(const std::string_view & str) \ + typename SettingField##NEW_NAME::EnumType SettingField##NEW_NAME##Traits::fromString(const std::string_view & str) \ { \ static const std::unordered_map map = [] { \ std::unordered_map res; \ diff --git a/src/IO/ReadHelpers.h b/src/IO/ReadHelpers.h index f299ab2286f..d11bd1d8706 100644 --- a/src/IO/ReadHelpers.h +++ b/src/IO/ReadHelpers.h @@ -638,7 +638,7 @@ template inline T parse(const char * data, size_t size); template -inline T parseFromString(const String & str) +inline T parseFromString(const std::string_view & str) { return parse(str.data(), str.size()); } @@ -1096,7 +1096,7 @@ inline T parseWithSizeSuffix(const char * data, size_t size) } template -inline T parseWithSizeSuffix(const String & s) +inline T parseWithSizeSuffix(const std::string_view & s) { return parseWithSizeSuffix(s.data(), s.size()); } diff --git a/src/Storages/Kafka/StorageKafka.cpp b/src/Storages/Kafka/StorageKafka.cpp index c0f7ef8e44d..9d7bc273cd2 100644 --- a/src/Storages/Kafka/StorageKafka.cpp +++ b/src/Storages/Kafka/StorageKafka.cpp @@ -173,7 +173,7 @@ SettingsChanges StorageKafka::createSettingsAdjustments() { if (it.isChanged() && it.getName().toString().rfind("kafka_",0) == std::string::npos) { - result.emplace_back(it.getName().toString(), it.getValueAsString()); + result.emplace_back(it.getName().toString(), it.getValue()); } } return result; @@ -632,8 +632,8 @@ void registerStorageKafka(StorageFactory & factory) engine_args[(ARG_NUM)-1], \ args.local_context); \ } \ - kafka_settings->PAR_NAME.set( \ - engine_args[(ARG_NUM)-1]->as().value);\ + kafka_settings->PAR_NAME = \ + engine_args[(ARG_NUM)-1]->as().value; \ } \ } diff --git a/src/Storages/StorageJoin.cpp b/src/Storages/StorageJoin.cpp index af1a8bf10d7..74097278026 100644 --- a/src/Storages/StorageJoin.cpp +++ b/src/Storages/StorageJoin.cpp @@ -124,17 +124,17 @@ void registerStorageJoin(StorageFactory & factory) for (const auto & setting : args.storage_def->settings->changes) { if (setting.name == "join_use_nulls") - join_use_nulls.set(setting.value); + join_use_nulls = setting.value; else if (setting.name == "max_rows_in_join") - max_rows_in_join.set(setting.value); + max_rows_in_join = setting.value; else if (setting.name == "max_bytes_in_join") - max_bytes_in_join.set(setting.value); + max_bytes_in_join = setting.value; else if (setting.name == "join_overflow_mode") - join_overflow_mode.set(setting.value); + join_overflow_mode = setting.value; else if (setting.name == "join_any_take_last_row") - join_any_take_last_row.set(setting.value); + join_any_take_last_row = setting.value; else if (setting.name == "any_join_distinct_right_table_keys") - old_any_join.set(setting.value); + old_any_join = setting.value; else throw Exception( "Unknown setting " + setting.name + " for storage " + args.engine_name,