diff --git a/programs/compressor/Compressor.cpp b/programs/compressor/Compressor.cpp index fecdad9bcea..701e8ea2d1c 100644 --- a/programs/compressor/Compressor.cpp +++ b/programs/compressor/Compressor.cpp @@ -63,6 +63,8 @@ void checkAndWriteHeader(DB::ReadBuffer & in, DB::WriteBuffer & out) int mainEntryClickHouseCompressor(int argc, char ** argv) { + using namespace DB; + boost::program_options::options_description desc = createOptionsDescription("Allowed options", getTerminalWidth()); desc.add_options() ("help,h", "produce help message") @@ -99,10 +101,10 @@ int mainEntryClickHouseCompressor(int argc, char ** argv) codecs = options["codec"].as>(); if ((use_lz4hc || use_zstd || use_none) && !codecs.empty()) - throw DB::Exception("Wrong options, codec flags like --zstd and --codec options are mutually exclusive", DB::ErrorCodes::BAD_ARGUMENTS); + throw Exception("Wrong options, codec flags like --zstd and --codec options are mutually exclusive", ErrorCodes::BAD_ARGUMENTS); if (!codecs.empty() && options.count("level")) - throw DB::Exception("Wrong options, --level is not compatible with --codec list", DB::ErrorCodes::BAD_ARGUMENTS); + throw Exception("Wrong options, --level is not compatible with --codec list", ErrorCodes::BAD_ARGUMENTS); std::string method_family = "LZ4"; @@ -117,22 +119,21 @@ int mainEntryClickHouseCompressor(int argc, char ** argv) if (options.count("level")) level = options["level"].as(); - - DB::CompressionCodecPtr codec; + CompressionCodecPtr codec; if (!codecs.empty()) { - DB::ParserCodec codec_parser; + ParserCodec codec_parser; std::string codecs_line = boost::algorithm::join(codecs, ","); - auto ast = DB::parseQuery(codec_parser, "(" + codecs_line + ")", 0, DBMS_DEFAULT_MAX_PARSER_DEPTH); - codec = DB::CompressionCodecFactory::instance().get(ast, nullptr); + auto ast = parseQuery(codec_parser, "(" + codecs_line + ")", 0, DBMS_DEFAULT_MAX_PARSER_DEPTH); + codec = CompressionCodecFactory::instance().get(ast, nullptr, false); } else - codec = DB::CompressionCodecFactory::instance().get(method_family, level); + codec = CompressionCodecFactory::instance().get(method_family, level, false); - DB::ReadBufferFromFileDescriptor rb(STDIN_FILENO); - DB::WriteBufferFromFileDescriptor wb(STDOUT_FILENO); + ReadBufferFromFileDescriptor rb(STDIN_FILENO); + WriteBufferFromFileDescriptor wb(STDOUT_FILENO); if (stat_mode) { @@ -142,20 +143,20 @@ int mainEntryClickHouseCompressor(int argc, char ** argv) else if (decompress) { /// Decompression - DB::CompressedReadBuffer from(rb); - DB::copyData(from, wb); + CompressedReadBuffer from(rb); + copyData(from, wb); } else { /// Compression - DB::CompressedWriteBuffer to(wb, codec, block_size); - DB::copyData(rb, to); + CompressedWriteBuffer to(wb, codec, block_size); + copyData(rb, to); } } catch (...) { - std::cerr << DB::getCurrentExceptionMessage(true); - return DB::getCurrentExceptionCode(); + std::cerr << getCurrentExceptionMessage(true); + return getCurrentExceptionCode(); } return 0; diff --git a/programs/server/TCPHandler.cpp b/programs/server/TCPHandler.cpp index 70825cb4f7e..f6903f0820f 100644 --- a/programs/server/TCPHandler.cpp +++ b/programs/server/TCPHandler.cpp @@ -1066,14 +1066,16 @@ void TCPHandler::initBlockOutput(const Block & block) { if (!state.maybe_compressed_out) { - std::string method = Poco::toUpper(query_context->getSettingsRef().network_compression_method.toString()); + const Settings & query_settings = query_context->getSettingsRef(); + + std::string method = Poco::toUpper(query_settings.network_compression_method.toString()); std::optional level; if (method == "ZSTD") - level = query_context->getSettingsRef().network_zstd_compression_level; + level = query_settings.network_zstd_compression_level; if (state.compression == Protocol::Compression::Enable) state.maybe_compressed_out = std::make_shared( - *out, CompressionCodecFactory::instance().get(method, level)); + *out, CompressionCodecFactory::instance().get(method, level, !query_settings.allow_suspicious_codecs)); else state.maybe_compressed_out = out; } diff --git a/src/Client/Connection.cpp b/src/Client/Connection.cpp index cc79e3ec2c8..7c46c82d810 100644 --- a/src/Client/Connection.cpp +++ b/src/Client/Connection.cpp @@ -379,7 +379,7 @@ void Connection::sendQuery( if (method == "ZSTD") level = settings->network_zstd_compression_level; - compression_codec = CompressionCodecFactory::instance().get(method, level); + compression_codec = CompressionCodecFactory::instance().get(method, level, !settings->allow_suspicious_codecs); } else compression_codec = CompressionCodecFactory::instance().getDefaultCodec(); diff --git a/src/Compression/CompressionCodecDelta.h b/src/Compression/CompressionCodecDelta.h index 6a5ad9330e2..1077a791535 100644 --- a/src/Compression/CompressionCodecDelta.h +++ b/src/Compression/CompressionCodecDelta.h @@ -23,6 +23,8 @@ protected: UInt32 getMaxCompressedDataSize(UInt32 uncompressed_size) const override { return uncompressed_size + 2; } + bool isCompression() const override { return false; } + bool isGenericCompression() const override { return false; } private: UInt8 delta_bytes_size; diff --git a/src/Compression/CompressionCodecDoubleDelta.h b/src/Compression/CompressionCodecDoubleDelta.h index 04bc112360e..d0a7f4df8f9 100644 --- a/src/Compression/CompressionCodecDoubleDelta.h +++ b/src/Compression/CompressionCodecDoubleDelta.h @@ -109,6 +109,9 @@ protected: UInt32 getMaxCompressedDataSize(UInt32 uncompressed_size) const override; + bool isCompression() const override { return true; } + bool isGenericCompression() const override { return false; } + private: UInt8 data_bytes_size; }; diff --git a/src/Compression/CompressionCodecGorilla.h b/src/Compression/CompressionCodecGorilla.h index e95de81afb0..d11aeed6056 100644 --- a/src/Compression/CompressionCodecGorilla.h +++ b/src/Compression/CompressionCodecGorilla.h @@ -106,6 +106,9 @@ protected: UInt32 getMaxCompressedDataSize(UInt32 uncompressed_size) const override; + bool isCompression() const override { return true; } + bool isGenericCompression() const override { return false; } + private: UInt8 data_bytes_size; }; diff --git a/src/Compression/CompressionCodecLZ4.h b/src/Compression/CompressionCodecLZ4.h index d53fced3681..a73dd48a36c 100644 --- a/src/Compression/CompressionCodecLZ4.h +++ b/src/Compression/CompressionCodecLZ4.h @@ -21,6 +21,9 @@ public: protected: UInt32 doCompressData(const char * source, UInt32 source_size, char * dest) const override; + bool isCompression() const override { return true; } + bool isGenericCompression() const override { return true; } + private: void doDecompressData(const char * source, UInt32 source_size, char * dest, UInt32 uncompressed_size) const override; diff --git a/src/Compression/CompressionCodecMultiple.cpp b/src/Compression/CompressionCodecMultiple.cpp index 294a8c7629b..b5caaa8d751 100644 --- a/src/Compression/CompressionCodecMultiple.cpp +++ b/src/Compression/CompressionCodecMultiple.cpp @@ -17,12 +17,34 @@ namespace DB namespace ErrorCodes { -extern const int CORRUPTED_DATA; + extern const int CORRUPTED_DATA; + extern const int BAD_ARGUMENTS; } -CompressionCodecMultiple::CompressionCodecMultiple(Codecs codecs_) +CompressionCodecMultiple::CompressionCodecMultiple(Codecs codecs_, bool sanity_check) : codecs(codecs_) { + if (sanity_check) + { + /// It does not make sense to apply any transformations after generic compression algorithm + /// So, generic compression can be only one and only at the end. + bool has_generic_compression = false; + for (const auto & codec : codecs) + { + if (codec->isNone()) + throw Exception("It does not make sense to have codec NONE along with other compression codecs: " + getCodecDescImpl() + + " (Note: you can enable setting 'allow_suspicious_codecs' to skip this check).", + ErrorCodes::BAD_ARGUMENTS); + + if (has_generic_compression) + throw Exception("The combination of compression codecs " + getCodecDescImpl() + " is meaningless, " + " because it does not make sense to apply any transformations after generic compression algorithm." + " (Note: you can enable setting 'allow_suspicious_codecs' to skip this check).", ErrorCodes::BAD_ARGUMENTS); + + if (codec->isGenericCompression()) + has_generic_compression = true; + } + } } uint8_t CompressionCodecMultiple::getMethodByte() const @@ -31,6 +53,11 @@ uint8_t CompressionCodecMultiple::getMethodByte() const } String CompressionCodecMultiple::getCodecDesc() const +{ + return getCodecDescImpl(); +} + +String CompressionCodecMultiple::getCodecDescImpl() const { WriteBufferFromOwnString out; for (size_t idx = 0; idx < codecs.size(); ++idx) @@ -120,6 +147,14 @@ void CompressionCodecMultiple::doDecompressData(const char * source, UInt32 sour memcpy(dest, compressed_buf.data(), decompressed_size); } +bool CompressionCodecMultiple::isCompression() const +{ + for (const auto & codec : codecs) + if (codec->isCompression()) + return true; + return false; +} + void registerCodecMultiple(CompressionCodecFactory & factory) { factory.registerSimpleCompressionCodec("Multiple", static_cast(CompressionMethodByte::Multiple), [&] () diff --git a/src/Compression/CompressionCodecMultiple.h b/src/Compression/CompressionCodecMultiple.h index 68d2c934fa3..ff208d619cb 100644 --- a/src/Compression/CompressionCodecMultiple.h +++ b/src/Compression/CompressionCodecMultiple.h @@ -9,7 +9,7 @@ class CompressionCodecMultiple final : public ICompressionCodec { public: CompressionCodecMultiple() = default; - explicit CompressionCodecMultiple(Codecs codecs_); + CompressionCodecMultiple(Codecs codecs_, bool sanity_check); uint8_t getMethodByte() const override; @@ -24,9 +24,13 @@ protected: void doDecompressData(const char * source, UInt32 source_size, char * dest, UInt32 decompressed_size) const override; + bool isCompression() const override; + bool isGenericCompression() const override { return false; } + private: Codecs codecs; + String getCodecDescImpl() const; }; diff --git a/src/Compression/CompressionCodecNone.h b/src/Compression/CompressionCodecNone.h index 168a15bec2f..ef7029e244b 100644 --- a/src/Compression/CompressionCodecNone.h +++ b/src/Compression/CompressionCodecNone.h @@ -20,6 +20,9 @@ protected: void doDecompressData(const char * source, UInt32 source_size, char * dest, UInt32 uncompressed_size) const override; + bool isCompression() const override { return false; } + bool isGenericCompression() const override { return false; } + bool isNone() const override { return true; } }; class CompressionCodecFactory; diff --git a/src/Compression/CompressionCodecT64.h b/src/Compression/CompressionCodecT64.h index c95e14e860d..cafc9959a9d 100644 --- a/src/Compression/CompressionCodecT64.h +++ b/src/Compression/CompressionCodecT64.h @@ -48,6 +48,9 @@ protected: return uncompressed_size + MAX_COMPRESSED_BLOCK_SIZE + HEADER_SIZE; } + bool isCompression() const override { return true; } + bool isGenericCompression() const override { return false; } + private: TypeIndex type_idx; Variant variant; diff --git a/src/Compression/CompressionCodecZSTD.h b/src/Compression/CompressionCodecZSTD.h index 045602c66ea..234f49b279b 100644 --- a/src/Compression/CompressionCodecZSTD.h +++ b/src/Compression/CompressionCodecZSTD.h @@ -26,6 +26,9 @@ protected: void doDecompressData(const char * source, UInt32 source_size, char * dest, UInt32 uncompressed_size) const override; + bool isCompression() const override { return true; } + bool isGenericCompression() const override { return true; } + private: const int level; }; diff --git a/src/Compression/CompressionFactory.cpp b/src/Compression/CompressionFactory.cpp index d58a42423c5..5d15924c1eb 100644 --- a/src/Compression/CompressionFactory.cpp +++ b/src/Compression/CompressionFactory.cpp @@ -29,22 +29,22 @@ CompressionCodecPtr CompressionCodecFactory::getDefaultCodec() const } -CompressionCodecPtr CompressionCodecFactory::get(const String & family_name, std::optional level) const +CompressionCodecPtr CompressionCodecFactory::get(const String & family_name, std::optional level, bool sanity_check) const { if (level) { auto literal = std::make_shared(static_cast(*level)); - return get(makeASTFunction("CODEC", makeASTFunction(Poco::toUpper(family_name), literal))); + return get(makeASTFunction("CODEC", makeASTFunction(Poco::toUpper(family_name), literal)), {}, sanity_check); } else { auto identifier = std::make_shared(Poco::toUpper(family_name)); - return get(makeASTFunction("CODEC", identifier)); + return get(makeASTFunction("CODEC", identifier), {}, sanity_check); } } -CompressionCodecPtr CompressionCodecFactory::get(const ASTPtr & ast, DataTypePtr column_type) const +CompressionCodecPtr CompressionCodecFactory::get(const ASTPtr & ast, DataTypePtr column_type, bool sanity_check) const { if (const auto * func = ast->as()) { @@ -60,10 +60,19 @@ CompressionCodecPtr CompressionCodecFactory::get(const ASTPtr & ast, DataTypePtr throw Exception("Unexpected AST element for compression codec", ErrorCodes::UNEXPECTED_AST_STRUCTURE); } + CompressionCodecPtr res; + if (codecs.size() == 1) - return codecs.back(); + res = codecs.back(); else if (codecs.size() > 1) - return std::make_shared(codecs); + res = std::make_shared(codecs, sanity_check); + + if (sanity_check && !res->isCompression()) + throw Exception("The combination of compression codecs " + res->getCodecDesc() + " does not compress anything." + " (Note: you can enable setting 'allow_suspicious_codecs' to skip this check).", + ErrorCodes::BAD_ARGUMENTS); + + return res; } throw Exception("Unknown codec family: " + queryToString(ast), ErrorCodes::UNKNOWN_CODEC); diff --git a/src/Compression/CompressionFactory.h b/src/Compression/CompressionFactory.h index 926929abd18..58799538f8c 100644 --- a/src/Compression/CompressionFactory.h +++ b/src/Compression/CompressionFactory.h @@ -40,13 +40,13 @@ public: /// Get codec by AST and possible column_type /// some codecs can use information about type to improve inner settings /// but every codec should be able to work without information about type - CompressionCodecPtr get(const ASTPtr & ast, DataTypePtr column_type = nullptr) const; + CompressionCodecPtr get(const ASTPtr & ast, DataTypePtr column_type, bool sanity_check) const; /// Get codec by method byte (no params available) CompressionCodecPtr get(const uint8_t byte_code) const; /// For backward compatibility with config settings - CompressionCodecPtr get(const String & family_name, std::optional level) const; + CompressionCodecPtr get(const String & family_name, std::optional level, bool sanity_check) const; /// Register codec with parameters and column type void registerCompressionCodecWithType(const String & family_name, std::optional byte_code, CreatorWithType creator); diff --git a/src/Compression/ICompressionCodec.h b/src/Compression/ICompressionCodec.h index 083824cf0ca..cac42ee61f4 100644 --- a/src/Compression/ICompressionCodec.h +++ b/src/Compression/ICompressionCodec.h @@ -57,7 +57,16 @@ public: static uint8_t readMethod(const char * source); /// Some codecs may use information about column type which appears after codec creation - virtual void useInfoAboutType(DataTypePtr /* data_type */) { } + virtual void useInfoAboutType(DataTypePtr /* data_type */) {} + + /// Return true if this codec actually compressing something. Otherwise it can be just transformation that helps compression (e.g. Delta). + virtual bool isCompression() const = 0; + + /// Is it a generic compression algorithm like lz4, zstd. Usually it does not make sense to apply generic compression more than single time. + virtual bool isGenericCompression() const = 0; + + /// If it does nothing. + virtual bool isNone() const { return false; } protected: diff --git a/src/Compression/tests/gtest_compressionCodec.cpp b/src/Compression/tests/gtest_compressionCodec.cpp index f3652366a24..eca1c3c0a8f 100644 --- a/src/Compression/tests/gtest_compressionCodec.cpp +++ b/src/Compression/tests/gtest_compressionCodec.cpp @@ -470,7 +470,7 @@ CompressionCodecPtr makeCodec(const std::string & codec_string, const DataTypePt parser.parse(token_iterator, codec_ast, expected); - return CompressionCodecFactory::instance().get(codec_ast, data_type); + return CompressionCodecFactory::instance().get(codec_ast, data_type, false); } template diff --git a/src/Core/Settings.h b/src/Core/Settings.h index 88b83be5add..d1a51d7a10c 100644 --- a/src/Core/Settings.h +++ b/src/Core/Settings.h @@ -265,6 +265,7 @@ struct Settings : public SettingsCollection M(SettingBool, joined_subquery_requires_alias, true, "Force joined subqueries and table functions to have aliases for correct name qualification.", 0) \ M(SettingBool, empty_result_for_aggregation_by_empty_set, false, "Return empty result when aggregating without keys on empty set.", 0) \ M(SettingBool, allow_distributed_ddl, true, "If it is set to true, then a user is allowed to executed distributed DDL queries.", 0) \ + M(SettingBool, allow_suspicious_codecs, false, "If it is set to true, allow to specify meaningless compression codecs.", 0) \ M(SettingUInt64, odbc_max_field_size, 1024, "Max size of filed can be read from ODBC dictionary. Long strings are truncated.", 0) \ M(SettingUInt64, query_profiler_real_time_period_ns, 1000000000, "Period for real clock timer of query profiler (in nanoseconds). Set 0 value to turn off the real clock query profiler. Recommended value is at least 10000000 (100 times a second) for single queries or 1000000000 (once a second) for cluster-wide profiling.", 0) \ M(SettingUInt64, query_profiler_cpu_time_period_ns, 1000000000, "Period for CPU clock timer of query profiler (in nanoseconds). Set 0 value to turn off the CPU clock query profiler. Recommended value is at least 10000000 (100 times a second) for single queries or 1000000000 (once a second) for cluster-wide profiling.", 0) \ diff --git a/src/DataStreams/TemporaryFileStream.h b/src/DataStreams/TemporaryFileStream.h index 6871800a540..ddb2190f175 100644 --- a/src/DataStreams/TemporaryFileStream.h +++ b/src/DataStreams/TemporaryFileStream.h @@ -37,7 +37,7 @@ struct TemporaryFileStream std::atomic * is_cancelled, const std::string & codec) { WriteBufferFromFile file_buf(path); - CompressedWriteBuffer compressed_buf(file_buf, CompressionCodecFactory::instance().get(codec, {})); + CompressedWriteBuffer compressed_buf(file_buf, CompressionCodecFactory::instance().get(codec, {}, false)); NativeBlockOutputStream output(compressed_buf, 0, header); copyData(input, output, is_cancelled); } diff --git a/src/Databases/DatabaseOnDisk.cpp b/src/Databases/DatabaseOnDisk.cpp index da38dc3b8f7..aed9f38c2ea 100644 --- a/src/Databases/DatabaseOnDisk.cpp +++ b/src/Databases/DatabaseOnDisk.cpp @@ -65,7 +65,7 @@ std::pair createTableFromAST( if (!ast_create_query.columns_list || !ast_create_query.columns_list->columns) throw Exception("Missing definition of columns.", ErrorCodes::EMPTY_LIST_OF_COLUMNS_PASSED); - ColumnsDescription columns = InterpreterCreateQuery::getColumnsDescription(*ast_create_query.columns_list->columns, context); + ColumnsDescription columns = InterpreterCreateQuery::getColumnsDescription(*ast_create_query.columns_list->columns, context, false); ConstraintsDescription constraints = InterpreterCreateQuery::getConstraintsDescription(ast_create_query.columns_list->constraints); return diff --git a/src/Interpreters/InterpreterAlterQuery.cpp b/src/Interpreters/InterpreterAlterQuery.cpp index c8517defdb7..c2ab8776c25 100644 --- a/src/Interpreters/InterpreterAlterQuery.cpp +++ b/src/Interpreters/InterpreterAlterQuery.cpp @@ -56,7 +56,7 @@ BlockIO InterpreterAlterQuery::execute() LiveViewCommands live_view_commands; for (ASTAlterCommand * command_ast : alter.command_list->commands) { - if (auto alter_command = AlterCommand::parse(command_ast)) + if (auto alter_command = AlterCommand::parse(command_ast, !context.getSettingsRef().allow_suspicious_codecs)) alter_commands.emplace_back(std::move(*alter_command)); else if (auto partition_command = PartitionCommand::parse(command_ast)) { diff --git a/src/Interpreters/InterpreterCreateQuery.cpp b/src/Interpreters/InterpreterCreateQuery.cpp index 43a0a7f608e..147ef7d739b 100644 --- a/src/Interpreters/InterpreterCreateQuery.cpp +++ b/src/Interpreters/InterpreterCreateQuery.cpp @@ -267,7 +267,8 @@ ASTPtr InterpreterCreateQuery::formatConstraints(const ConstraintsDescription & return res; } -ColumnsDescription InterpreterCreateQuery::getColumnsDescription(const ASTExpressionList & columns_ast, const Context & context) +ColumnsDescription InterpreterCreateQuery::getColumnsDescription( + const ASTExpressionList & columns_ast, const Context & context, bool sanity_check_compression_codecs) { /// First, deduce implicit types. @@ -355,7 +356,7 @@ ColumnsDescription InterpreterCreateQuery::getColumnsDescription(const ASTExpres column.comment = col_decl.comment->as().value.get(); if (col_decl.codec) - column.codec = CompressionCodecFactory::instance().get(col_decl.codec, column.type); + column.codec = CompressionCodecFactory::instance().get(col_decl.codec, column.type, sanity_check_compression_codecs); if (col_decl.ttl) column.ttl = col_decl.ttl; @@ -390,7 +391,10 @@ InterpreterCreateQuery::TableProperties InterpreterCreateQuery::setProperties(AS if (create.columns_list) { if (create.columns_list->columns) - properties.columns = getColumnsDescription(*create.columns_list->columns, context); + { + bool sanity_check_compression_codecs = !create.attach && !context.getSettingsRef().allow_suspicious_codecs; + properties.columns = getColumnsDescription(*create.columns_list->columns, context, sanity_check_compression_codecs); + } if (create.columns_list->indices) for (const auto & index : create.columns_list->indices->children) diff --git a/src/Interpreters/InterpreterCreateQuery.h b/src/Interpreters/InterpreterCreateQuery.h index c52c12b2e4b..2ce98b7b2c2 100644 --- a/src/Interpreters/InterpreterCreateQuery.h +++ b/src/Interpreters/InterpreterCreateQuery.h @@ -46,7 +46,7 @@ public: } /// Obtain information about columns, their types, default values and column comments, for case when columns in CREATE query is specified explicitly. - static ColumnsDescription getColumnsDescription(const ASTExpressionList & columns, const Context & context); + static ColumnsDescription getColumnsDescription(const ASTExpressionList & columns, const Context & context, bool sanity_check_compression_codecs); static ConstraintsDescription getConstraintsDescription(const ASTExpressionList * constraints); private: diff --git a/src/Interpreters/InterpreterSystemQuery.cpp b/src/Interpreters/InterpreterSystemQuery.cpp index ebf4875b435..caa7dfb69d5 100644 --- a/src/Interpreters/InterpreterSystemQuery.cpp +++ b/src/Interpreters/InterpreterSystemQuery.cpp @@ -343,7 +343,7 @@ StoragePtr InterpreterSystemQuery::tryRestartReplica(const StorageID & replica, auto & create = create_ast->as(); create.attach = true; - auto columns = InterpreterCreateQuery::getColumnsDescription(*create.columns_list->columns, system_context); + auto columns = InterpreterCreateQuery::getColumnsDescription(*create.columns_list->columns, system_context, false); auto constraints = InterpreterCreateQuery::getConstraintsDescription(create.columns_list->constraints); auto data_path = database->getTableDataPath(create); diff --git a/src/Storages/AlterCommands.cpp b/src/Storages/AlterCommands.cpp index 04639ea0e3d..121974c8b82 100644 --- a/src/Storages/AlterCommands.cpp +++ b/src/Storages/AlterCommands.cpp @@ -44,7 +44,7 @@ namespace ErrorCodes } -std::optional AlterCommand::parse(const ASTAlterCommand * command_ast) +std::optional AlterCommand::parse(const ASTAlterCommand * command_ast, bool sanity_check_compression_codecs) { const DataTypeFactory & data_type_factory = DataTypeFactory::instance(); const CompressionCodecFactory & compression_codec_factory = CompressionCodecFactory::instance(); @@ -75,7 +75,7 @@ std::optional AlterCommand::parse(const ASTAlterCommand * command_ } if (ast_col_decl.codec) - command.codec = compression_codec_factory.get(ast_col_decl.codec, command.data_type); + command.codec = compression_codec_factory.get(ast_col_decl.codec, command.data_type, sanity_check_compression_codecs); if (command_ast->column) command.after_column = getIdentifierName(command_ast->column); @@ -131,7 +131,7 @@ std::optional AlterCommand::parse(const ASTAlterCommand * command_ command.ttl = ast_col_decl.ttl; if (ast_col_decl.codec) - command.codec = compression_codec_factory.get(ast_col_decl.codec, command.data_type); + command.codec = compression_codec_factory.get(ast_col_decl.codec, command.data_type, sanity_check_compression_codecs); command.if_exists = command_ast->if_exists; diff --git a/src/Storages/AlterCommands.h b/src/Storages/AlterCommands.h index 4e40c1ee190..c1c913dad73 100644 --- a/src/Storages/AlterCommands.h +++ b/src/Storages/AlterCommands.h @@ -100,7 +100,7 @@ struct AlterCommand /// Target column name String rename_to; - static std::optional parse(const ASTAlterCommand * command); + static std::optional parse(const ASTAlterCommand * command, bool sanity_check_compression_codecs); void apply(StorageInMemoryMetadata & metadata) const; diff --git a/src/Storages/ColumnsDescription.cpp b/src/Storages/ColumnsDescription.cpp index 14c0da01a73..8c92307dcb7 100644 --- a/src/Storages/ColumnsDescription.cpp +++ b/src/Storages/ColumnsDescription.cpp @@ -120,7 +120,7 @@ void ColumnDescription::readText(ReadBuffer & buf) comment = col_ast->comment->as().value.get(); if (col_ast->codec) - codec = CompressionCodecFactory::instance().get(col_ast->codec, type); + codec = CompressionCodecFactory::instance().get(col_ast->codec, type, false); if (col_ast->ttl) ttl = col_ast->ttl; diff --git a/src/Storages/CompressionCodecSelector.h b/src/Storages/CompressionCodecSelector.h index d194adc9317..0924550fcea 100644 --- a/src/Storages/CompressionCodecSelector.h +++ b/src/Storages/CompressionCodecSelector.h @@ -91,7 +91,7 @@ public: for (const auto & element : elements) if (element.check(part_size, part_size_ratio)) - res = factory.get(element.family_name, element.level); + res = factory.get(element.family_name, element.level, false); return res; } diff --git a/src/TableFunctions/parseColumnsListForTableFunction.cpp b/src/TableFunctions/parseColumnsListForTableFunction.cpp index c419164ac38..8eea3edf9bd 100644 --- a/src/TableFunctions/parseColumnsListForTableFunction.cpp +++ b/src/TableFunctions/parseColumnsListForTableFunction.cpp @@ -31,7 +31,7 @@ ColumnsDescription parseColumnsListFromString(const std::string & structure, con if (!columns_list) throw Exception("Could not cast AST to ASTExpressionList", ErrorCodes::LOGICAL_ERROR); - return InterpreterCreateQuery::getColumnsDescription(*columns_list, context); + return InterpreterCreateQuery::getColumnsDescription(*columns_list, context, !context.getSettingsRef().allow_suspicious_codecs); } }