Ban non comparable types in primary key

This commit is contained in:
alesapin 2020-11-02 14:39:27 +03:00
parent 7a92960a11
commit f3b3025719
5 changed files with 24 additions and 3 deletions

View File

@ -512,6 +512,7 @@ namespace ErrorCodes
extern const int NO_ROW_DELIMITER = 546; extern const int NO_ROW_DELIMITER = 546;
extern const int INVALID_RAID_TYPE = 547; extern const int INVALID_RAID_TYPE = 547;
extern const int UNKNOWN_VOLUME = 548; extern const int UNKNOWN_VOLUME = 548;
extern const int DATA_TYPE_CANNOT_BE_USED_IN_KEY = 549;
extern const int KEEPER_EXCEPTION = 999; extern const int KEEPER_EXCEPTION = 999;
extern const int POCO_EXCEPTION = 1000; extern const int POCO_EXCEPTION = 1000;

View File

@ -26,6 +26,7 @@ namespace ErrorCodes
extern const int NOT_IMPLEMENTED; extern const int NOT_IMPLEMENTED;
extern const int LOGICAL_ERROR; extern const int LOGICAL_ERROR;
extern const int ILLEGAL_TYPE_OF_ARGUMENT; extern const int ILLEGAL_TYPE_OF_ARGUMENT;
extern const int LOGICAL_ERROR;
} }
template <typename T, typename SFINAE = void> template <typename T, typename SFINAE = void>
@ -767,9 +768,10 @@ T & Field::get()
#ifndef NDEBUG #ifndef NDEBUG
// Disregard signedness when converting between int64 types. // Disregard signedness when converting between int64 types.
constexpr Field::Types::Which target = TypeToEnum<NearestFieldType<ValueType>>::value; constexpr Field::Types::Which target = TypeToEnum<NearestFieldType<ValueType>>::value;
assert(target == which if (target != which
|| (isInt64FieldType(target) && isInt64FieldType(which)) && (!isInt64FieldType(target) || !isInt64FieldType(which))
|| target == Field::Types::Decimal64 /* DateTime64 fields */); && target != Field::Types::Decimal64 /* DateTime64 fields */)
throw Exception(ErrorCodes::LOGICAL_ERROR, "Invalid Field get from type {} to type {}", Types::toString(which), Types::toString(target));
#endif #endif
ValueType * MAY_ALIAS ptr = reinterpret_cast<ValueType *>(&storage); ValueType * MAY_ALIAS ptr = reinterpret_cast<ValueType *>(&storage);

View File

@ -2,10 +2,12 @@
#include <Functions/IFunction.h> #include <Functions/IFunction.h>
#include <Parsers/ASTIdentifier.h> #include <Parsers/ASTIdentifier.h>
#include <DataTypes/DataTypeAggregateFunction.h>
#include <Interpreters/ExpressionActions.h> #include <Interpreters/ExpressionActions.h>
#include <Interpreters/ExpressionAnalyzer.h> #include <Interpreters/ExpressionAnalyzer.h>
#include <Interpreters/TreeRewriter.h> #include <Interpreters/TreeRewriter.h>
#include <Storages/extractKeyExpressionList.h> #include <Storages/extractKeyExpressionList.h>
#include <Common/quoteString.h>
namespace DB namespace DB
@ -14,6 +16,7 @@ namespace DB
namespace ErrorCodes namespace ErrorCodes
{ {
extern const int LOGICAL_ERROR; extern const int LOGICAL_ERROR;
extern const int DATA_TYPE_CANNOT_BE_USED_IN_KEY;
} }
KeyDescription::KeyDescription(const KeyDescription & other) KeyDescription::KeyDescription(const KeyDescription & other)
@ -115,7 +118,13 @@ KeyDescription KeyDescription::getSortingKeyFromAST(
} }
for (size_t i = 0; i < result.sample_block.columns(); ++i) for (size_t i = 0; i < result.sample_block.columns(); ++i)
{
result.data_types.emplace_back(result.sample_block.getByPosition(i).type); result.data_types.emplace_back(result.sample_block.getByPosition(i).type);
if (!result.data_types.back()->isComparable())
throw Exception(ErrorCodes::DATA_TYPE_CANNOT_BE_USED_IN_KEY,
"Column {} with type {} is not allowed in key expression, it's not comparable",
backQuote(result.sample_block.getByPosition(i).name), result.data_types.back()->getName());
}
return result; return result;
} }

View File

@ -0,0 +1,9 @@
DROP TABLE IF EXISTS uncomparable_keys;
CREATE TABLE foo (id UInt64, key AggregateFunction(max, UInt64)) ENGINE MergeTree ORDER BY key; --{serverError 549}
CREATE TABLE foo (id UInt64, key AggregateFunction(max, UInt64)) ENGINE MergeTree PARTITION BY key; --{serverError 549}
CREATE TABLE foo (id UInt64, key AggregateFunction(max, UInt64)) ENGINE MergeTree ORDER BY (key) SAMPLE BY key; --{serverError 549}
DROP TABLE IF EXISTS uncomparable_keys;