Coverage Report

Created: 2026-07-20 21:29

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
be/src/exec/sink/viceberg_delete_sink.h
Line
Count
Source
1
// Licensed to the Apache Software Foundation (ASF) under one
2
// or more contributor license agreements.  See the NOTICE file
3
// distributed with this work for additional information
4
// regarding copyright ownership.  The ASF licenses this file
5
// to you under the Apache License, Version 2.0 (the
6
// "License"); you may not use this file except in compliance
7
// with the License.  You may obtain a copy of the License at
8
//
9
//   http://www.apache.org/licenses/LICENSE-2.0
10
//
11
// Unless required by applicable law or agreed to in writing,
12
// software distributed under the License is distributed on an
13
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
// KIND, either express or implied.  See the License for the
15
// specific language governing permissions and limitations
16
// under the License.
17
18
#pragma once
19
20
#include <gen_cpp/DataSinks_types.h>
21
#include <gen_cpp/PlanNodes_types.h>
22
23
#include <cstddef>
24
#include <cstdint>
25
#include <map>
26
#include <memory>
27
#include <string>
28
#include <vector>
29
30
#include "common/status.h"
31
#include "core/block/block.h"
32
#include "exec/sink/writer/async_result_writer.h"
33
#include "exec/sink/writer/iceberg/viceberg_delete_file_writer.h"
34
#include "exprs/vexpr_fwd.h"
35
#include "roaring/roaring64map.hh"
36
#include "runtime/runtime_profile.h"
37
38
namespace doris {
39
40
class ObjectPool;
41
class RuntimeState;
42
class Dependency;
43
44
class VIcebergDeleteFileWriter;
45
46
Status calculate_iceberg_deletion_vector_content_size(size_t bitmap_size, int64_t* content_size);
47
48
struct IcebergFileDeletion {
49
    IcebergFileDeletion() = default;
50
    IcebergFileDeletion(int32_t spec_id, std::string data_json)
51
323
            : partition_spec_id(spec_id), partition_data_json(std::move(data_json)) {}
52
53
    int32_t partition_spec_id = 0;
54
    std::string partition_data_json;
55
    roaring::Roaring64Map rows_to_delete;
56
};
57
58
/**
59
 * Sink for writing Iceberg position delete files.
60
 *
61
 * This sink receives blocks containing a $row_id column with
62
 * (file_path, row_position, partition_spec_id, partition_data).
63
 * It groups delete records by file_path and writes position delete files.
64
 */
65
class VIcebergDeleteSink final : public AsyncResultWriter {
66
public:
67
    VIcebergDeleteSink(const TDataSink& t_sink, const VExprContextSPtrs& output_exprs,
68
                       std::shared_ptr<Dependency> dep, std::shared_ptr<Dependency> fin_dep);
69
70
2.16k
    ~VIcebergDeleteSink() override = default;
71
72
    Status init_properties(ObjectPool* pool);
73
74
    Status open(RuntimeState* state, RuntimeProfile* profile) override;
75
76
    Status write(RuntimeState* state, Block& block) override;
77
78
    Status close(Status) override;
79
80
private:
81
    /**
82
     * Extract $row_id column from block and group by file_path.
83
     */
84
    Status _collect_position_deletes(const Block& block,
85
                                     std::map<std::string, IcebergFileDeletion>& file_deletions);
86
87
    /**
88
     * Write grouped position deletes to delete files
89
     */
90
    Status _write_position_delete_files(
91
            const std::map<std::string, IcebergFileDeletion>& file_deletions);
92
93
    Status _write_deletion_vector_files(
94
            const std::map<std::string, IcebergFileDeletion>& file_deletions);
95
96
    struct DeletionVectorBlob {
97
        std::string referenced_data_file;
98
        int32_t partition_spec_id = 0;
99
        std::string partition_data_json;
100
        int64_t delete_count = 0; // The number of rows deleted in this delete operation.
101
        int64_t merged_count =
102
                0; // The number of rows after merging the old deletion vector and position delete.
103
        int64_t content_offset = 0;
104
        int64_t content_size_in_bytes = 0;
105
        std::vector<char> blob_data;
106
    };
107
108
    Status _write_puffin_file(const std::string& puffin_path,
109
                              std::vector<DeletionVectorBlob>* blobs, int64_t* out_file_size);
110
111
    std::string _build_puffin_footer_json(const std::vector<DeletionVectorBlob>& blobs);
112
113
    std::string _generate_puffin_file_path();
114
115
    /**
116
     * Generate unique delete file path
117
     */
118
    std::string _generate_delete_file_path(const std::string& referenced_data_file = "");
119
120
    /**
121
     * Get $row_id column index from block
122
     */
123
    int _get_row_id_column_index(const Block& block);
124
125
    /**
126
     * Build a block for position delete (file_path, pos)
127
     */
128
    Status _build_position_delete_block(const std::string& file_path,
129
                                        const std::vector<int64_t>& positions, Block& output_block);
130
    Status _init_position_delete_output_exprs();
131
    std::string _get_file_extension() const;
132
133
    TDataSink _t_sink;
134
    RuntimeState* _state = nullptr;
135
136
    int32_t _format_version = 2;
137
    TFileContent::type _delete_type = TFileContent::POSITION_DELETES;
138
139
    // Writers for delete files
140
    std::vector<std::unique_ptr<VIcebergDeleteFileWriter>> _writers;
141
142
    // Collected commit data from all writers
143
    std::vector<TIcebergCommitData> _commit_data_list;
144
    // TODO: All deletions are held in memory until close(). Consider flushing
145
    //  per-file when the upstream guarantees file_path ordering, or flushing
146
    //  when estimated memory exceeds a threshold, to reduce peak memory usage.
147
    std::map<std::string, IcebergFileDeletion> _file_deletions;
148
    std::map<std::string, std::vector<TIcebergDeleteFileDesc>> _rewritable_delete_files;
149
150
    // Hadoop configuration
151
    std::map<std::string, std::string> _hadoop_conf;
152
153
    // File format settings
154
    TFileFormatType::type _file_format_type = TFileFormatType::FORMAT_PARQUET;
155
    TFileCompressType::type _compress_type = TFileCompressType::SNAPPYBLOCK;
156
157
    // Output directory for delete files
158
    std::string _output_path;
159
    std::string _table_location;
160
161
    TFileType::type _file_type = TFileType::FILE_HDFS;
162
    std::vector<TNetworkAddress> _broker_addresses;
163
164
    // Partition information
165
    int32_t _partition_spec_id = 0;
166
    std::string _partition_data_json;
167
168
    // Counters
169
    size_t _row_count = 0;
170
    size_t _delete_file_count = 0;
171
172
    // Profile counters
173
    RuntimeProfile::Counter* _written_rows_counter = nullptr;
174
    RuntimeProfile::Counter* _send_data_timer = nullptr;
175
    RuntimeProfile::Counter* _write_delete_files_timer = nullptr;
176
    RuntimeProfile::Counter* _delete_file_count_counter = nullptr;
177
    RuntimeProfile::Counter* _open_timer = nullptr;
178
    RuntimeProfile::Counter* _close_timer = nullptr;
179
180
    VExprContextSPtrs _position_delete_output_expr_ctxs;
181
};
182
183
} // namespace doris