mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-12-12 09:22:05 +00:00
Optimize the code and streamline the functionality by retaining only the feature of automatically recognizing UInt64 as Int64.
This commit is contained in:
parent
12d262ed7a
commit
efb041c4d5
@ -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) \
|
||||
|
@ -18,9 +18,10 @@ class DataTypeNumber final : public DataTypeNumberBase<T>
|
||||
public:
|
||||
DataTypeNumber() = default;
|
||||
|
||||
explicit DataTypeNumber(DataTypes data_types)
|
||||
explicit DataTypeNumber(DataTypePtr opposite_sign_data_type_)
|
||||
: DataTypeNumberBase<T>()
|
||||
, 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<PromotedType>();
|
||||
}
|
||||
|
||||
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<SerializationNumber<T>>();
|
||||
}
|
||||
|
||||
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<UInt8>;
|
||||
|
@ -33,34 +33,19 @@ DataTypePtr FieldToDataType<on_error>::operator() (const Null &) const
|
||||
template <LeastSupertypeOnError on_error>
|
||||
DataTypePtr FieldToDataType<on_error>::operator() (const UInt64 & x) const
|
||||
{
|
||||
if (x <= std::numeric_limits<Int8>::max()) return std::make_shared<DataTypeUInt8>(DataTypes{ std::make_shared<DataTypeInt8>() });
|
||||
if (x <= std::numeric_limits<UInt8>::max()) return std::make_shared<DataTypeUInt8>();
|
||||
if (x <= std::numeric_limits<Int16>::max()) return std::make_shared<DataTypeUInt16>(DataTypes{ std::make_shared<DataTypeInt16>() });
|
||||
if (x <= std::numeric_limits<UInt16>::max()) return std::make_shared<DataTypeUInt16>();
|
||||
if (x <= std::numeric_limits<Int32>::max()) return std::make_shared<DataTypeUInt32>(DataTypes{ std::make_shared<DataTypeInt32>() });
|
||||
if (x <= std::numeric_limits<UInt32>::max()) return std::make_shared<DataTypeUInt32>();
|
||||
if (x <= std::numeric_limits<Int64>::max()) return std::make_shared<DataTypeUInt64>(DataTypes{ std::make_shared<DataTypeInt64>() });
|
||||
if (x <= std::numeric_limits<Int64>::max()) return std::make_shared<DataTypeUInt64>(std::make_shared<DataTypeInt64>());
|
||||
return std::make_shared<DataTypeUInt64>();
|
||||
}
|
||||
|
||||
template <LeastSupertypeOnError on_error>
|
||||
DataTypePtr FieldToDataType<on_error>::operator() (const Int64 & x) const
|
||||
{
|
||||
if (x >= 0)
|
||||
{
|
||||
if (x <= std::numeric_limits<Int8>::max()) return std::make_shared<DataTypeInt8>();
|
||||
if (x <= std::numeric_limits<UInt8>::max()) return std::make_shared<DataTypeInt16>(DataTypes{ std::make_shared<DataTypeUInt8>() });
|
||||
if (x <= std::numeric_limits<Int16>::max()) return std::make_shared<DataTypeInt16>();
|
||||
if (x <= std::numeric_limits<UInt16>::max()) return std::make_shared<DataTypeInt32>(DataTypes{ std::make_shared<DataTypeUInt16>() });
|
||||
if (x <= std::numeric_limits<Int32>::max()) return std::make_shared<DataTypeInt32>();
|
||||
if (x <= std::numeric_limits<UInt32>::max()) return std::make_shared<DataTypeInt64>(DataTypes{ std::make_shared<DataTypeUInt32>() });
|
||||
}
|
||||
else
|
||||
{
|
||||
if (x >= std::numeric_limits<Int8>::min()) return std::make_shared<DataTypeInt8>();
|
||||
if (x >= std::numeric_limits<Int16>::min()) return std::make_shared<DataTypeInt16>();
|
||||
if (x >= std::numeric_limits<Int32>::min()) return std::make_shared<DataTypeInt32>();
|
||||
}
|
||||
if (x <= std::numeric_limits<Int8>::max() && x >= std::numeric_limits<Int8>::min()) return std::make_shared<DataTypeInt8>();
|
||||
if (x <= std::numeric_limits<Int16>::max() && x >= std::numeric_limits<Int16>::min()) return std::make_shared<DataTypeInt16>();
|
||||
if (x <= std::numeric_limits<Int32>::max() && x >= std::numeric_limits<Int32>::min()) return std::make_shared<DataTypeInt32>();
|
||||
return std::make_shared<DataTypeInt64>();
|
||||
}
|
||||
|
||||
|
@ -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());
|
||||
|
@ -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).
|
||||
*/
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user