diff --git a/dbms/include/DB/Core/Block.h b/dbms/include/DB/Core/Block.h index 5446446dd1c..df308561726 100644 --- a/dbms/include/DB/Core/Block.h +++ b/dbms/include/DB/Core/Block.h @@ -20,6 +20,8 @@ namespace DB * Позволяет вставлять, удалять столбцы в любом порядке, менять порядок столбцов. */ +class Context; + class Block { public: @@ -54,6 +56,7 @@ public: void insert(size_t position, const ColumnWithNameAndType & elem); /// вставить столбец в конец void insert(const ColumnWithNameAndType & elem); + void insertDefault(const String & name, const DataTypePtr & type); /// вставить столбец в конец, если столбца с таким именем ещё нет void insertUnique(const ColumnWithNameAndType & elem); /// удалить столбец в заданной позиции @@ -61,7 +64,7 @@ public: /// удалить столбец с заданным именем void erase(const String & name); /// Добавляет в блок недостающие столбцы со значениями по-умолчанию - void addDefaults(NamesAndTypesListPtr required_columns); + void addDefaults(const NamesAndTypesList & required_columns); ColumnWithNameAndType & getByPosition(size_t position); const ColumnWithNameAndType & getByPosition(size_t position) const; diff --git a/dbms/include/DB/DataStreams/AddingDefaultBlockInputStream.h b/dbms/include/DB/DataStreams/AddingDefaultBlockInputStream.h index 2a24ff99f4e..fd1357d7b7a 100644 --- a/dbms/include/DB/DataStreams/AddingDefaultBlockInputStream.h +++ b/dbms/include/DB/DataStreams/AddingDefaultBlockInputStream.h @@ -3,8 +3,10 @@ #include #include +#include #include +#include namespace DB @@ -19,12 +21,20 @@ class AddingDefaultBlockInputStream : public IProfilingBlockInputStream public: AddingDefaultBlockInputStream( BlockInputStreamPtr input_, - NamesAndTypesListPtr required_columns_) - : required_columns(required_columns_) + NamesAndTypesListPtr required_columns_, + const ColumnDefaults & column_defaults_, + const Context & context_) + : required_columns(required_columns_), + column_defaults(column_defaults_), context(context_) { children.push_back(input_); } + AddingDefaultBlockInputStream(BlockInputStreamPtr input_, NamesAndTypesListPtr required_columns_, const Context & context_) + : AddingDefaultBlockInputStream{input_, required_columns, {}, context} + { + } + String getName() const override { return "AddingDefaultBlockInputStream"; } String getID() const override @@ -45,12 +55,15 @@ protected: Block res = children.back()->read(); if (!res) return res; - res.addDefaults(required_columns); + evaluateMissingDefaults(res, *required_columns, column_defaults, context); + res.addDefaults(*required_columns); return res; } private: NamesAndTypesListPtr required_columns; + const ColumnDefaults & column_defaults; + Context context; }; } diff --git a/dbms/include/DB/DataStreams/AddingDefaultBlockOutputStream.h b/dbms/include/DB/DataStreams/AddingDefaultBlockOutputStream.h index 7652d55dac9..b6228b1218c 100644 --- a/dbms/include/DB/DataStreams/AddingDefaultBlockOutputStream.h +++ b/dbms/include/DB/DataStreams/AddingDefaultBlockOutputStream.h @@ -5,6 +5,9 @@ #include #include +#include +#include +#include namespace DB @@ -19,15 +22,25 @@ class AddingDefaultBlockOutputStream : public IBlockOutputStream public: AddingDefaultBlockOutputStream( BlockOutputStreamPtr output_, - NamesAndTypesListPtr required_columns_) - : output(output_), required_columns(required_columns_) + NamesAndTypesListPtr required_columns_, + const ColumnDefaults & column_defaults_, + const Context & context_) + : output(output_), required_columns(required_columns_), + column_defaults(column_defaults_), context(context_) { } + AddingDefaultBlockOutputStream(BlockOutputStreamPtr output_, NamesAndTypesListPtr required_columns_, const Context & context_) + : AddingDefaultBlockOutputStream{output_, required_columns_, {}, context_} + { + } + + void write(const Block & block) override { Block res = block; - res.addDefaults(required_columns); + evaluateMissingDefaults(res, *required_columns, column_defaults, context); + res.addDefaults(*required_columns); output->write(res); } @@ -39,6 +52,8 @@ public: private: BlockOutputStreamPtr output; NamesAndTypesListPtr required_columns; + const ColumnDefaults & column_defaults; + Context context; }; diff --git a/dbms/include/DB/DataStreams/MaterializingBlockOutputStream.h b/dbms/include/DB/DataStreams/MaterializingBlockOutputStream.h new file mode 100644 index 00000000000..641a522373a --- /dev/null +++ b/dbms/include/DB/DataStreams/MaterializingBlockOutputStream.h @@ -0,0 +1,37 @@ +#pragma once + +#include +#include +#include + + +namespace DB +{ + +/** Преобразует столбцы-константы в полноценные столбцы ("материализует" их). + */ +class MaterializingBlockOutputStream : public IBlockOutputStream +{ +public: + MaterializingBlockOutputStream(const BlockOutputStreamPtr & output) : output{output} + {} + + void write(const Block & original_block) override + { + /// copy block to get rid of const + auto block = original_block; + + for (const auto i : ext::range(0, block.columns())) + { + ColumnPtr & col = block.getByPosition(i).column; + if (col->isConst()) + col = dynamic_cast(*col).convertToFullColumn(); + } + + output->write(block); + } + + BlockOutputStreamPtr output; +}; + +} diff --git a/dbms/include/DB/DataStreams/ProhibitColumnsBlockOutputStream.h b/dbms/include/DB/DataStreams/ProhibitColumnsBlockOutputStream.h new file mode 100644 index 00000000000..296aa202fe5 --- /dev/null +++ b/dbms/include/DB/DataStreams/ProhibitColumnsBlockOutputStream.h @@ -0,0 +1,39 @@ +#pragma once + +#include + + +namespace DB +{ + + +/// Throws exception on encountering prohibited column in block +class ProhibitColumnsBlockOutputStream : public IBlockOutputStream +{ +public: + ProhibitColumnsBlockOutputStream(const BlockOutputStreamPtr & output, const NamesAndTypesList & columns) + : output{output}, columns{columns} + { + } + +private: + void write(const Block & block) override + { + for (const auto & column : columns) + if (block.has(column.name)) + throw Exception{"Cannot insert column " + column.name, ErrorCodes::ILLEGAL_COLUMN}; + + output->write(block); + } + + void flush() override { output->flush(); } + + void writePrefix() override { output->writePrefix(); } + void writeSuffix() override { output->writeSuffix(); } + + BlockOutputStreamPtr output; + NamesAndTypesList columns; +}; + + +} diff --git a/dbms/include/DB/Functions/FunctionFactory.h b/dbms/include/DB/Functions/FunctionFactory.h index 5900365995a..71a7ea796ce 100644 --- a/dbms/include/DB/Functions/FunctionFactory.h +++ b/dbms/include/DB/Functions/FunctionFactory.h @@ -25,9 +25,10 @@ public: FunctionPtr get(const String & name, const Context & context) const; - void registerFunction(const String & name, Creator creator) + template void registerFunction() { - functions[name] = creator; + static_assert(std::is_same::value, "F::create has incorrect type"); + functions[F::name] = &F::create; } }; diff --git a/dbms/include/DB/Functions/FunctionsArithmetic.h b/dbms/include/DB/Functions/FunctionsArithmetic.h index 0c4542b43e4..72dcf215602 100644 --- a/dbms/include/DB/Functions/FunctionsArithmetic.h +++ b/dbms/include/DB/Functions/FunctionsArithmetic.h @@ -367,6 +367,10 @@ struct BinaryOperationTraits template