diff --git a/src/Common/ErrorCodes.cpp b/src/Common/ErrorCodes.cpp index ae8d5f8796d..3df92c941e8 100644 --- a/src/Common/ErrorCodes.cpp +++ b/src/Common/ErrorCodes.cpp @@ -582,6 +582,9 @@ M(697, CANNOT_RESTORE_TO_NONENCRYPTED_DISK) \ M(698, INVALID_REDIS_STORAGE_TYPE) \ M(699, INVALID_REDIS_TABLE_STRUCTURE) \ + M(700, USER_SESSION_LIMIT_EXCEEDED) \ + M(701, CLUSTER_DOESNT_EXIST) \ + M(702, OPPOSITE_SIGN_DATA_TYPE_NOT_FOUND) \ \ M(999, KEEPER_EXCEPTION) \ M(1000, POCO_EXCEPTION) \ diff --git a/src/DataTypes/DataTypesNumber.h b/src/DataTypes/DataTypesNumber.h index 8511955e193..6be07db1062 100644 --- a/src/DataTypes/DataTypesNumber.h +++ b/src/DataTypes/DataTypesNumber.h @@ -18,9 +18,10 @@ class DataTypeNumber final : public DataTypeNumberBase public: DataTypeNumber() = default; - explicit DataTypeNumber(DataTypes data_types) + explicit DataTypeNumber(DataTypePtr opposite_sign_data_type_) : DataTypeNumberBase() - , possible_data_types(std::move(data_types)) + , opposite_sign_data_type(std::move(opposite_sign_data_type_)) + , has_opposite_sign_data_type(true) { } @@ -39,15 +40,23 @@ public: return std::make_shared(); } + bool hasOppositeSignDataType() const override { return has_opposite_sign_data_type; } + DataTypePtr oppositeSignDataType() const override + { + if (!has_opposite_sign_data_type) + IDataType::oppositeSignDataType(); + + return opposite_sign_data_type; + } + SerializationPtr doGetDefaultSerialization() const override { return std::make_shared>(); } - DataTypes getPossiblePtr() const override { return possible_data_types; } - private: - DataTypes possible_data_types; + DataTypePtr opposite_sign_data_type; + bool has_opposite_sign_data_type = false; }; using DataTypeUInt8 = DataTypeNumber; diff --git a/src/DataTypes/FieldToDataType.cpp b/src/DataTypes/FieldToDataType.cpp index 9b8e476067e..2f759e79661 100644 --- a/src/DataTypes/FieldToDataType.cpp +++ b/src/DataTypes/FieldToDataType.cpp @@ -33,34 +33,19 @@ DataTypePtr FieldToDataType::operator() (const Null &) const template DataTypePtr FieldToDataType::operator() (const UInt64 & x) const { - if (x <= std::numeric_limits::max()) return std::make_shared(DataTypes{ std::make_shared() }); if (x <= std::numeric_limits::max()) return std::make_shared(); - if (x <= std::numeric_limits::max()) return std::make_shared(DataTypes{ std::make_shared() }); if (x <= std::numeric_limits::max()) return std::make_shared(); - if (x <= std::numeric_limits::max()) return std::make_shared(DataTypes{ std::make_shared() }); if (x <= std::numeric_limits::max()) return std::make_shared(); - if (x <= std::numeric_limits::max()) return std::make_shared(DataTypes{ std::make_shared() }); + if (x <= std::numeric_limits::max()) return std::make_shared(std::make_shared()); return std::make_shared(); } template DataTypePtr FieldToDataType::operator() (const Int64 & x) const { - if (x >= 0) - { - if (x <= std::numeric_limits::max()) return std::make_shared(); - if (x <= std::numeric_limits::max()) return std::make_shared(DataTypes{ std::make_shared() }); - if (x <= std::numeric_limits::max()) return std::make_shared(); - if (x <= std::numeric_limits::max()) return std::make_shared(DataTypes{ std::make_shared() }); - if (x <= std::numeric_limits::max()) return std::make_shared(); - if (x <= std::numeric_limits::max()) return std::make_shared(DataTypes{ std::make_shared() }); - } - else - { - if (x >= std::numeric_limits::min()) return std::make_shared(); - if (x >= std::numeric_limits::min()) return std::make_shared(); - if (x >= std::numeric_limits::min()) return std::make_shared(); - } + if (x <= std::numeric_limits::max() && x >= std::numeric_limits::min()) return std::make_shared(); + if (x <= std::numeric_limits::max() && x >= std::numeric_limits::min()) return std::make_shared(); + if (x <= std::numeric_limits::max() && x >= std::numeric_limits::min()) return std::make_shared(); return std::make_shared(); } diff --git a/src/DataTypes/IDataType.cpp b/src/DataTypes/IDataType.cpp index 4ffe82039b2..221254e575e 100644 --- a/src/DataTypes/IDataType.cpp +++ b/src/DataTypes/IDataType.cpp @@ -23,6 +23,7 @@ namespace ErrorCodes { extern const int LOGICAL_ERROR; extern const int DATA_TYPE_CANNOT_BE_PROMOTED; + extern const int OPPOSITE_SIGN_DATA_TYPE_NOT_FOUND; extern const int ILLEGAL_COLUMN; } @@ -71,6 +72,11 @@ DataTypePtr IDataType::promoteNumericType() const throw Exception(ErrorCodes::DATA_TYPE_CANNOT_BE_PROMOTED, "Data type {} can't be promoted.", getName()); } +DataTypePtr IDataType::oppositeSignDataType() const +{ + throw Exception(ErrorCodes::OPPOSITE_SIGN_DATA_TYPE_NOT_FOUND, "Opposite sign data type not found for {}.", getName()); +} + size_t IDataType::getSizeOfValueInMemory() const { throw Exception(ErrorCodes::LOGICAL_ERROR, "Value of type {} in memory is not of fixed size.", getName()); diff --git a/src/DataTypes/IDataType.h b/src/DataTypes/IDataType.h index 52962462d7e..867ed6df5e3 100644 --- a/src/DataTypes/IDataType.h +++ b/src/DataTypes/IDataType.h @@ -73,8 +73,6 @@ public: DataTypePtr getPtr() const { return shared_from_this(); } - virtual DataTypes getPossiblePtr() const { return {}; } - /// Name of data type family (example: FixedString, Array). virtual const char * getFamilyName() const = 0; /// Name of corresponding data type in MySQL (exampe: Bigint, Blob, etc) @@ -160,6 +158,15 @@ public: */ virtual DataTypePtr promoteNumericType() const; + /** The data type has an opposite sign DataTypePtr type. + * Data types that can have an opposite sign are typically signed or unsigned types. + */ + virtual bool hasOppositeSignDataType() const { return false; } + + /** Return the opposite sign data type of the current data type. Throw an exception if `hasOppositeSignDataType() == false`. + */ + virtual DataTypePtr oppositeSignDataType() const; + /** Directly insert default value into a column. Default implementation use method IColumn::insertDefault. * This should be overridden if data type default value differs from column default value (example: Enum data types). */ diff --git a/src/DataTypes/getLeastSupertype.cpp b/src/DataTypes/getLeastSupertype.cpp index d8be5fab91e..4c399e99caa 100644 --- a/src/DataTypes/getLeastSupertype.cpp +++ b/src/DataTypes/getLeastSupertype.cpp @@ -605,113 +605,50 @@ DataTypePtr getLeastSupertype(const DataTypes & types, bool optimize_type_ids) void optimizeTypeIds(const DataTypes & types, TypeIndexSet & type_ids) { - // Determine whether the type_id is UInt - auto is_unsigned = [](const TypeIndex & type_id) + auto is_signed_int = [](const TypeIndex & type_id) { switch (type_id) { - case TypeIndex::UInt8: - case TypeIndex::UInt16: - case TypeIndex::UInt32: - case TypeIndex::UInt64: + case TypeIndex::Int8: + case TypeIndex::Int16: + case TypeIndex::Int32: + case TypeIndex::Int64: return true; default: return false; } }; - bool only_unsigned = false; - bool only_signed = false; - bool both = false; - bool has_unsigned = false; - bool has_signed = false; + bool has_signed_int = false; + bool has_uint64_and_has_opposite = false; + TypeIndexSet opposite_type_ids; - // Determine the distribution of maximum signed and unsigned, Example: - // Int64, Int64 = only_signed. - // UInt64, UInt64 = only_unsigned. - // UInt64(possible: Int64), Int64(possible: UInt64) = both. - // UInt64(possible: Int64), Int64 = both, only_signed. + // Determine whether UInt64 in type_ids needs to change its sign. for (const auto & type : types) { - TypeIndex type_id = type->getTypeId(); - bool type_is_unsigned = is_unsigned(type_id); - bool type_is_both = false; - for (const auto & possible_type : type->getPossiblePtr()) + auto type_id = type->getTypeId(); + + if (!has_signed_int) + has_signed_int = is_signed_int(type_id); + + if (type_id == TypeIndex::UInt64) { - if (type_is_unsigned != is_unsigned(possible_type->getTypeId())) + if (!type->hasOppositeSignDataType()) { - type_is_both = true; - break; + has_uint64_and_has_opposite = false; + break ; + }else + { + has_uint64_and_has_opposite = true; + opposite_type_ids.insert(type->oppositeSignDataType()->getTypeId()); } } - - if (type_is_unsigned) - has_unsigned = true; - else - has_signed = true; - - if (type_is_both) - both = true; - else if (type_is_unsigned) - only_unsigned = true; - else - only_signed = true; } - auto optimize_type_id = [&is_unsigned](const DataTypePtr & type, bool try_change_unsigned) + if (has_uint64_and_has_opposite && has_signed_int) { - TypeIndex type_id = type->getTypeId(); - switch (type_id) - { - case TypeIndex::UInt8: - case TypeIndex::UInt16: - case TypeIndex::UInt32: - case TypeIndex::UInt64: - if (try_change_unsigned) - return type_id; - break ; - case TypeIndex::Int8: - case TypeIndex::Int16: - case TypeIndex::Int32: - case TypeIndex::Int64: - if (!try_change_unsigned) - return type_id; - break ; - default: - return type_id; - } - - for (const auto & other_type : type->getPossiblePtr()) - { - TypeIndex other_type_id = other_type->getTypeId(); - if ((try_change_unsigned && is_unsigned(other_type_id)) - || (!try_change_unsigned && !is_unsigned(other_type_id))) - { - return other_type_id; - } - } - - return type_id; - }; - - // optimize type_ids - if (both) - { - // Example: Int64(possible: UInt32), UInt64 = UInt32, UInt64 - if (only_unsigned && !only_signed) - { - type_ids.clear(); - for (const auto & type : types) - type_ids.insert(optimize_type_id(type, true)); - } - // Example: UInt64(possible: Int64), Int64 = Int64, Int64 - // Int64(possible: UInt32), UInt64(possible: Int64) = Int64, Int64 - else if ((only_signed && !only_unsigned) || (has_unsigned && has_signed && !only_signed && !only_unsigned)) - { - type_ids.clear(); - for (const auto & type : types) - type_ids.insert(optimize_type_id(type, false)); - } + type_ids.erase(TypeIndex::UInt64); + type_ids.insert(opposite_type_ids.begin(), opposite_type_ids.end()); } }