#include #include #include #include #include #include #include #include #include #include #include #include #include namespace DB { namespace ErrorCodes { extern const int LOGICAL_ERROR; extern const int NUMBER_OF_ARGUMENTS_DOESNT_MATCH; } void TableFunctionFormat::parseArguments(const ASTPtr & ast_function, ContextPtr context) { ASTs & args_func = ast_function->children; if (args_func.size() != 1) throw Exception("Table function '" + getName() + "' must have arguments", ErrorCodes::LOGICAL_ERROR); ASTs & args = args_func.at(0)->children; if (args.size() != 2) throw Exception("Table function '" + getName() + "' requires 2 arguments: format and data", ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH); for (auto & arg : args) arg = evaluateConstantExpressionOrIdentifierAsLiteral(arg, context); format = checkAndGetLiteralArgument(args[0], "format"); data = checkAndGetLiteralArgument(args[1], "data"); } ColumnsDescription TableFunctionFormat::getActualTableStructure(ContextPtr context) const { ReadBufferIterator read_buffer_iterator = [&]() { return std::make_unique(data); }; return readSchemaFromFormat(format, std::nullopt, read_buffer_iterator, false, context); } Block TableFunctionFormat::parseData(ColumnsDescription columns, ContextPtr context) const { Block block; for (const auto & name_and_type : columns.getAllPhysical()) block.insert({name_and_type.type->createColumn(), name_and_type.type, name_and_type.name}); auto read_buf = std::make_unique(data); auto input_format = context->getInputFormat(format, *read_buf, block, context->getSettingsRef().max_block_size); auto pipeline = std::make_unique(input_format); auto reader = std::make_unique(*pipeline); std::vector blocks; while (reader->pull(block)) blocks.push_back(std::move(block)); if (blocks.size() == 1) return blocks[0]; /// In case when data contains more then 1 block we combine /// them all to one big block (this is considered a rare case). return concatenateBlocks(blocks); } StoragePtr TableFunctionFormat::executeImpl(const ASTPtr & /*ast_function*/, ContextPtr context, const std::string & table_name, ColumnsDescription /*cached_columns*/) const { auto columns = getActualTableStructure(context); Block res_block = parseData(columns, context); auto res = std::make_shared(StorageID(getDatabaseName(), table_name), columns, res_block); res->startup(); return res; } void registerTableFunctionFormat(TableFunctionFactory & factory) { factory.registerFunction(TableFunctionFactory::CaseInsensitive); } }