Coverage Report

Created: 2026-07-02 13:50

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
be/src/format_v2/expr/delete_predicate.cpp
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
#include "format_v2/expr/delete_predicate.h"
19
20
#include <fmt/format.h>
21
#include <gen_cpp/Exprs_types.h>
22
#include <glog/logging.h>
23
24
#include <algorithm>
25
#include <cstddef>
26
#include <ostream>
27
28
#include "common/status.h"
29
#include "core/block/block.h"
30
#include "core/block/column_numbers.h"
31
#include "core/block/column_with_type_and_name.h"
32
#include "core/block/columns_with_type_and_name.h"
33
34
namespace doris::format {
35
36
DeletePredicate::DeletePredicate(const std::vector<int64_t>& deleted_rows)
37
22
        : VExpr(), _deleted_rows(deleted_rows) {
38
22
    _node_type = TExprNodeType::PREDICATE;
39
22
    _opcode = TExprOpcode::DELETE;
40
22
    _data_type = std::make_shared<DataTypeBool>();
41
22
}
42
43
Status DeletePredicate::prepare(RuntimeState* state, const RowDescriptor& desc,
44
10
                                VExprContext* context) {
45
10
    RETURN_IF_ERROR_OR_PREPARED(VExpr::prepare(state, desc, context));
46
10
    _expr_name = "DeletePredicate";
47
10
    _prepare_finished = true;
48
10
    return Status::OK();
49
10
}
50
51
Status DeletePredicate::open(RuntimeState* state, VExprContext* context,
52
10
                             FunctionContext::FunctionStateScope scope) {
53
10
    DCHECK(_prepare_finished);
54
10
    RETURN_IF_ERROR_OR_PREPARED(VExpr::open(state, context, scope));
55
0
    _open_finished = true;
56
0
    return Status::OK();
57
0
}
58
59
10
void DeletePredicate::close(VExprContext* context, FunctionContext::FunctionStateScope scope) {
60
10
    VExpr::close(context, scope);
61
10
}
62
63
/**
64
 * DeletePredicate is derived from 2 cases:
65
 * 1. All row IDs indicates deleted rows. (e.g. Delete rows with row_id in (1, 2, 3))
66
 * 2. Bit vector indicates whether each row is deleted or not. (e.g. Bit vector[0,1,0,0,1] indicates row 1 and row 4 are deleted)
67
 *
68
 * So DeletePredicate should have exactly 1 child expr, which is the slot of row id.
69
 * Row IDs should be generated by file reader as a virtual column in `block`.
70
 **/
71
17
Status DeletePredicate::execute(VExprContext* context, Block* block, int* result_column_id) const {
72
17
    if (_children.size() != 1) {
73
1
        return Status::InternalError(fmt::format(
74
1
                "DeletePredicate should have exactly 1 child expr, but got {}", _children.size()));
75
1
    }
76
16
    int slot = -1;
77
16
    RETURN_IF_ERROR(_children[0]->execute(context, block, &slot));
78
16
    if (slot < 0 || static_cast<size_t>(slot) >= block->columns()) {
79
1
        return Status::InternalError(
80
1
                "DeletePredicate row id child returned invalid column id {}, block has {} columns",
81
1
                slot, block->columns());
82
1
    }
83
15
    const auto& row_ids =
84
15
            assert_cast<const ColumnInt64&>(*block->get_by_position(slot).column).get_data();
85
15
    const auto count = row_ids.size();
86
15
    auto res_col = ColumnBool::create(count, 0);
87
15
    if (_deleted_rows.empty()) {
88
1
        block->insert({std::move(res_col), std::make_shared<DataTypeBool>(), expr_name()});
89
1
        *result_column_id = static_cast<int>(block->get_columns().size() - 1);
90
1
        return Status::OK();
91
1
    }
92
14
    if (count == 0) {
93
1
        block->insert({std::move(res_col), std::make_shared<DataTypeBool>(), expr_name()});
94
1
        *result_column_id = static_cast<int>(block->get_columns().size() - 1);
95
1
        return Status::OK();
96
1
    }
97
13
    const int64_t* delete_rows = _deleted_rows.data();
98
13
    const int64_t* delete_rows_end = delete_rows + _deleted_rows.size();
99
13
    const int64_t* start_pos = std::lower_bound(delete_rows, delete_rows_end, row_ids[0]);
100
13
    int64_t start_index = start_pos - delete_rows;
101
13
    const int64_t* end_pos = std::upper_bound(start_pos, delete_rows_end, row_ids[count - 1]);
102
13
    const int64_t end_index = end_pos - delete_rows;
103
104
33
    while (start_index < end_index) {
105
20
        int64_t delete_row = delete_rows[start_index];
106
20
        if (const auto it = std::ranges::lower_bound(row_ids, delete_row);
107
20
            it != row_ids.end() && *it == delete_row) {
108
20
            const size_t index = it - row_ids.begin();
109
20
            res_col->get_data()[index] = true;
110
20
        }
111
20
        ++start_index;
112
20
    }
113
13
    block->insert({std::move(res_col), std::make_shared<DataTypeBool>(), expr_name()});
114
13
    *result_column_id = static_cast<int>(block->get_columns().size() - 1);
115
13
    return Status::OK();
116
14
}
117
118
1
std::string DeletePredicate::debug_string() const {
119
1
    return _expr_name;
120
1
}
121
122
} // namespace doris::format