From 6f65176285e52ac0b9f82883671c28efd0fa4011 Mon Sep 17 00:00:00 2001 From: Alexey Milovidov Date: Sun, 23 Apr 2017 10:59:49 +0300 Subject: [PATCH] Explicitly disallow dummy data types and special Null data type to be in table declaration [#CLICKHOUSE-4]. --- dbms/src/Core/ErrorCodes.cpp | 1 + dbms/src/DataTypes/DataTypeNull.h | 5 +++++ dbms/src/DataTypes/IDataType.h | 3 +++ dbms/src/DataTypes/IDataTypeDummy.h | 23 ++++++++++++++--------- dbms/src/Storages/StorageFactory.cpp | 14 ++++++++++++++ dbms/src/Storages/StorageFactory.h | 1 + 6 files changed, 38 insertions(+), 9 deletions(-) diff --git a/dbms/src/Core/ErrorCodes.cpp b/dbms/src/Core/ErrorCodes.cpp index 39ab2327d1..2d4d8a2661 100644 --- a/dbms/src/Core/ErrorCodes.cpp +++ b/dbms/src/Core/ErrorCodes.cpp @@ -372,6 +372,7 @@ namespace ErrorCodes extern const int TOO_MUCH_FETCHES = 367; extern const int BAD_CAST = 368; extern const int ALL_REPLICAS_ARE_STALE = 369; + extern const int DATA_TYPE_CANNOT_BE_USED_IN_TABLES = 370; extern const int KEEPER_EXCEPTION = 999; extern const int POCO_EXCEPTION = 1000; diff --git a/dbms/src/DataTypes/DataTypeNull.h b/dbms/src/DataTypes/DataTypeNull.h index 94c086bfb0..733524a839 100644 --- a/dbms/src/DataTypes/DataTypeNull.h +++ b/dbms/src/DataTypes/DataTypeNull.h @@ -26,6 +26,11 @@ public: return true; } + bool notForTables() const override + { + return true; + } + DataTypePtr clone() const override { return std::make_shared(); diff --git a/dbms/src/DataTypes/IDataType.h b/dbms/src/DataTypes/IDataType.h index 7af7e214a6..ad5b6639af 100644 --- a/dbms/src/DataTypes/IDataType.h +++ b/dbms/src/DataTypes/IDataType.h @@ -43,6 +43,9 @@ public: /// relevant for it? True for numbers. False for Date and DateTime types. virtual bool behavesAsNumber() const { return false; } + /// If this data type cannot appear in table declaration - only for intermediate values of calculations. + virtual bool notForTables() const { return false; } + virtual DataTypePtr clone() const = 0; /** Binary serialization for range of values in column - for writing to disk/network, etc. diff --git a/dbms/src/DataTypes/IDataTypeDummy.h b/dbms/src/DataTypes/IDataTypeDummy.h index 0ec965fe6e..01873f9cdd 100644 --- a/dbms/src/DataTypes/IDataTypeDummy.h +++ b/dbms/src/DataTypes/IDataTypeDummy.h @@ -14,35 +14,40 @@ namespace DB class IDataTypeDummy : public IDataType { private: + bool notForTables() const override + { + return true; + } + void throwNoSerialization() const { throw Exception("Serialization is not implemented for data type " + getName(), ErrorCodes::NOT_IMPLEMENTED); } public: - void serializeBinary(const Field & field, WriteBuffer & ostr) const override { throwNoSerialization(); } - void deserializeBinary(Field & field, ReadBuffer & istr) const override { throwNoSerialization(); } - void serializeBinary(const IColumn & column, size_t row_num, WriteBuffer & ostr) const override { throwNoSerialization(); } - void deserializeBinary(IColumn & column, ReadBuffer & istr) const override { throwNoSerialization(); } + void serializeBinary(const Field & field, WriteBuffer & ostr) const override { throwNoSerialization(); } + void deserializeBinary(Field & field, ReadBuffer & istr) const override { throwNoSerialization(); } + void serializeBinary(const IColumn & column, size_t row_num, WriteBuffer & ostr) const override { throwNoSerialization(); } + void deserializeBinary(IColumn & column, ReadBuffer & istr) const override { throwNoSerialization(); } void serializeBinaryBulk(const IColumn & column, WriteBuffer & ostr, size_t offset, size_t limit) const override { throwNoSerialization(); } void deserializeBinaryBulk(IColumn & column, ReadBuffer & istr, size_t limit, double avg_value_size_hint) const override { throwNoSerialization(); } - void serializeText(const IColumn & column, size_t row_num, WriteBuffer & ostr) const override { throwNoSerialization(); } + void serializeText(const IColumn & column, size_t row_num, WriteBuffer & ostr) const override { throwNoSerialization(); } - void serializeTextEscaped(const IColumn & column, size_t row_num, WriteBuffer & ostr) const override { throwNoSerialization(); } + void serializeTextEscaped(const IColumn & column, size_t row_num, WriteBuffer & ostr) const override { throwNoSerialization(); } void deserializeTextEscaped(IColumn & column, ReadBuffer & istr) const override { throwNoSerialization(); } void serializeTextQuoted(const IColumn & column, size_t row_num, WriteBuffer & ostr) const override { throwNoSerialization(); } - void deserializeTextQuoted(IColumn & column, ReadBuffer & istr) const override { throwNoSerialization(); } + void deserializeTextQuoted(IColumn & column, ReadBuffer & istr) const override { throwNoSerialization(); } - void serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr, bool) const override { throwNoSerialization(); } + void serializeTextJSON(const IColumn & column, size_t row_num, WriteBuffer & ostr, bool) const override { throwNoSerialization(); } void deserializeTextJSON(IColumn & column, ReadBuffer & istr) const override { throwNoSerialization(); } void serializeTextCSV(const IColumn & column, size_t row_num, WriteBuffer & ostr) const override { throwNoSerialization(); } - void deserializeTextCSV(IColumn & column, ReadBuffer & istr, const char delimiter) const override { throwNoSerialization(); } + void deserializeTextCSV(IColumn & column, ReadBuffer & istr, const char delimiter) const override { throwNoSerialization(); } ColumnPtr createColumn() const override { diff --git a/dbms/src/Storages/StorageFactory.cpp b/dbms/src/Storages/StorageFactory.cpp index 8fd654a792..0639c700a8 100644 --- a/dbms/src/Storages/StorageFactory.cpp +++ b/dbms/src/Storages/StorageFactory.cpp @@ -51,6 +51,7 @@ namespace ErrorCodes extern const int FUNCTION_CANNOT_HAVE_PARAMETERS; extern const int TYPE_MISMATCH; extern const int INCORRECT_NUMBER_OF_COLUMNS; + extern const int DATA_TYPE_CANNOT_BE_USED_IN_TABLES; } @@ -224,6 +225,15 @@ static void setGraphitePatternsFromConfig(const Context & context, } +/// Some types are only for intermediate values of expressions and cannot be used in tables. +static void checkAllTypesAreAllowedInTable(const NamesAndTypesList & names_and_types) +{ + for (const auto & elem : names_and_types) + if (elem.type->notForTables()) + throw Exception("Data type " + elem.type->getName() + " cannot be used in tables", ErrorCodes::DATA_TYPE_CANNOT_BE_USED_IN_TABLES); +} + + StoragePtr StorageFactory::get( const String & name, const String & data_path, @@ -239,6 +249,10 @@ StoragePtr StorageFactory::get( bool attach, bool has_force_restore_data_flag) const { + checkAllTypesAreAllowedInTable(*columns); + checkAllTypesAreAllowedInTable(materialized_columns); + checkAllTypesAreAllowedInTable(alias_columns); + if (name == "Log") { return StorageLog::create( diff --git a/dbms/src/Storages/StorageFactory.h b/dbms/src/Storages/StorageFactory.h index e3fbfb4f5a..9ed7543526 100644 --- a/dbms/src/Storages/StorageFactory.h +++ b/dbms/src/Storages/StorageFactory.h @@ -11,6 +11,7 @@ class Context; /** Allows you to create a table by the name of the engine. + * In 'columns', 'materialized_columns', etc., Nested data structures must be flattened. */ class StorageFactory : public Singleton { -- GitLab