1. get projection pipeline and a sink to write parts 2. build an executor that can write block to the input stream (actually we can write through it to generate as many parts as possible) 3. finalize the pipeline so that all parts are merged into one part
| 872 | // 2. build an executor that can write block to the input stream (actually we can write through it to generate as many parts as possible) |
| 873 | // 3. finalize the pipeline so that all parts are merged into one part |
| 874 | std::optional<size_t> MergeTreeDataMutator::writeWithProjections( |
| 875 | MergeTreeData::MutableDataPartPtr new_data_part, |
| 876 | const StorageMetadataPtr & metadata_snapshot, |
| 877 | const MergeTreeProjections & projections_to_build, |
| 878 | BlockInputStreamPtr mutating_stream, |
| 879 | IMergedBlockOutputStream & out, |
| 880 | time_t time_of_mutation, |
| 881 | ManipulationListEntry & manipulation_entry, |
| 882 | const ReservationPtr & space_reservation, |
| 883 | TableLockHolder & holder, |
| 884 | ContextPtr context, |
| 885 | IMergeTreeDataPart::MinMaxIndex * minmax_idx) |
| 886 | { |
| 887 | std::optional<size_t> row_exists_count = is_delete_command ? std::make_optional(0ull) : std::nullopt; |
| 888 | size_t block_num = 0; |
| 889 | Block block; |
| 890 | std::map<String, MergeTreeData::MutableDataPartsVector> projection_parts; |
| 891 | std::vector<SquashingTransform> projection_squashes; |
| 892 | for (size_t i = 0, size = projections_to_build.size(); i < size; ++i) |
| 893 | { |
| 894 | projection_squashes.emplace_back(65536, 65536 * 256); |
| 895 | } |
| 896 | |
| 897 | LOG_DEBUG(log, "Begin to write with projections, part name is {}, need to rebuild {} projections", new_data_part->name, projections_to_build.size()); |
| 898 | |
| 899 | while (checkOperationIsNotCanceled(manipulation_entry) && (block = mutating_stream->read())) |
| 900 | { |
| 901 | if (minmax_idx) |
| 902 | minmax_idx->update(block, data.getMinMaxColumnsNames(metadata_snapshot->getPartitionKey())); |
| 903 | |
| 904 | /// Count how many rows are existing when writing blocks. It will be stored in part metadata. |
| 905 | if (is_delete_command) |
| 906 | { |
| 907 | auto row_exists_column = block.getByName(RowExistsColumn::ROW_EXISTS_COLUMN.name).column; |
| 908 | for (size_t i = 0; i < block.rows(); ++i) |
| 909 | { |
| 910 | if (row_exists_column->getBool(i)) |
| 911 | ++*row_exists_count; |
| 912 | } |
| 913 | } |
| 914 | |
| 915 | out.write(block); |
| 916 | |
| 917 | for (size_t i = 0, size = projections_to_build.size(); i < size; ++i) |
| 918 | { |
| 919 | const auto & projection = projections_to_build[i]->projection; |
| 920 | auto in = InterpreterSelectQuery( |
| 921 | projection.query_ast, |
| 922 | context, |
| 923 | Pipe(std::make_shared<SourceFromSingleChunk>(block, Chunk(block.getColumns(), block.rows()))), |
| 924 | SelectQueryOptions{ |
| 925 | projection.type == ProjectionDescription::Type::Normal ? QueryProcessingStage::FetchColumns : QueryProcessingStage::WithMergeableState}) |
| 926 | .execute() |
| 927 | .getInputStream(); |
| 928 | in = std::make_shared<SquashingBlockInputStream>(in, block.rows(), std::numeric_limits<UInt64>::max()); |
| 929 | in->readPrefix(); |
| 930 | auto & projection_squash = projection_squashes[i]; |
| 931 | auto projection_block = projection_squash.add(in->read()); |
nothing calls this directly
no test coverage detected