| 137 | } |
| 138 | |
| 139 | void TableWriteStep::transformPipeline(QueryPipeline & pipeline, const BuildQueryPipelineSettings & settings) |
| 140 | { |
| 141 | switch (target->getTargetType()) |
| 142 | { |
| 143 | case TargetType::INSERT: { |
| 144 | auto * insert_target = dynamic_cast<TableWriteStep::InsertTarget *>(target.get()); |
| 145 | auto target_storage = DatabaseCatalog::instance().getTable(insert_target->getStorageID(), settings.context); |
| 146 | |
| 147 | auto insert_target_header = getHeader(insert_target->getColumns()); |
| 148 | auto out_streams = createOutputStream( |
| 149 | target_storage, settings, insert_target_header, settings.context->getSettingsRef().max_threads, false, insert_target->getQuery()); |
| 150 | |
| 151 | if (out_streams.empty()) |
| 152 | throw Exception("No output stream when transform TableWriteStep", ErrorCodes::LOGICAL_ERROR); |
| 153 | |
| 154 | const auto & header = out_streams[0]->getHeader(); |
| 155 | auto actions_dag = ActionsDAG::makeConvertingActions( |
| 156 | pipeline.getHeader().getColumnsWithTypeAndName(), |
| 157 | header.getColumnsWithTypeAndName(), |
| 158 | ActionsDAG::MatchColumnsMode::Position); |
| 159 | auto actions = std::make_shared<ExpressionActions>( |
| 160 | actions_dag, ExpressionActionsSettings::fromContext(settings.context, CompileExpressions::yes)); |
| 161 | |
| 162 | pipeline.addSimpleTransform( |
| 163 | [&](const Block & in_header) -> ProcessorPtr { return std::make_shared<ExpressionTransform>(in_header, actions); }); |
| 164 | |
| 165 | size_t min_insert_block_size_rows = settings.context->getSettingsRef().min_insert_block_size_rows; |
| 166 | size_t min_insert_block_size_bytes = settings.context->getSettingsRef().min_insert_block_size_bytes; |
| 167 | /// It's important to squash blocks as early as possible (before other transforms), |
| 168 | /// because other transforms may work inefficient if block size is small. |
| 169 | |
| 170 | /// Do not squash blocks if it is a sync INSERT into Distributed, since it lead to double bufferization on client and server side. |
| 171 | /// Client-side bufferization might cause excessive timeouts (especially in case of big blocks). |
| 172 | if (!(settings.context->getSettingsRef().insert_distributed_sync && target_storage->isRemote()) && settings.context->getSettingsRef().enable_insert_squashing) |
| 173 | { |
| 174 | pipeline.addSimpleTransform( |
| 175 | [&](const Block & current_header) -> ProcessorPtr { |
| 176 | return std::make_shared<SimpleSquashingChunksTransform>(current_header, min_insert_block_size_rows, min_insert_block_size_bytes);} |
| 177 | ); |
| 178 | LOG_INFO(&Poco::Logger::get("TableWriteStep"), fmt::format("squash min insert block size rows:{}, min insert block size bytes:{}", min_insert_block_size_rows, min_insert_block_size_bytes)); |
| 179 | } |
| 180 | //LOG_DEBUG(&Poco::Logger::get("TableWriteStep"), fmt::format("output header: {}", stream->getHeader().dumpStructure())); |
| 181 | pipeline.resize(out_streams.size()); |
| 182 | LOG_INFO(&Poco::Logger::get("TableWriteStep"), fmt::format("pipeline size: {}, out streams size {}", pipeline.getNumStreams(), out_streams.size())); |
| 183 | |
| 184 | if (insert_select_with_profiles) |
| 185 | { |
| 186 | pipeline.addSimpleTransform([&](const Block &, QueryPipeline::StreamType type) -> ProcessorPtr |
| 187 | { |
| 188 | if (type != QueryPipeline::StreamType::Main) |
| 189 | return nullptr; |
| 190 | |
| 191 | auto stream = std::move(out_streams.back()); |
| 192 | out_streams.pop_back(); |
| 193 | |
| 194 | return std::make_shared<ProcessorToOutputStream>(std::move(stream)); |
| 195 | }); |
| 196 | } |
nothing calls this directly
no test coverage detected