Coverage Report

Created: 2024-11-20 15:53

/root/doris/be/src/olap/delete_handler.cpp
Line
Count
Source (jump to first uncovered line)
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 "olap/delete_handler.h"
19
20
#include <gen_cpp/PaloInternalService_types.h>
21
#include <gen_cpp/olap_file.pb.h>
22
#include <thrift/protocol/TDebugProtocol.h>
23
24
#include <boost/regex.hpp>
25
#include <sstream>
26
#include <string>
27
#include <vector>
28
29
#include "common/config.h"
30
#include "common/logging.h"
31
#include "common/status.h"
32
#include "olap/block_column_predicate.h"
33
#include "olap/column_predicate.h"
34
#include "olap/olap_common.h"
35
#include "olap/predicate_creator.h"
36
#include "olap/tablet_schema.h"
37
#include "olap/utils.h"
38
#include "util/debug_points.h"
39
40
using apache::thrift::ThriftDebugString;
41
using std::vector;
42
using std::string;
43
using std::stringstream;
44
45
using ::google::protobuf::RepeatedPtrField;
46
47
namespace doris {
48
using namespace ErrorCode;
49
50
// construct sub condition from TCondition
51
87
std::string construct_sub_predicate(const TCondition& condition) {
52
87
    string op = condition.condition_op;
53
87
    if (op == "<") {
54
50
        op += "<";
55
50
    } else if (op == ">") {
56
3
        op += ">";
57
3
    }
58
87
    string condition_str;
59
87
    if ("IS" == op) {
60
        // ATTN: tricky! Surround IS with spaces to make it "special"
61
1
        condition_str = condition.column_name + " IS " + condition.condition_values[0];
62
86
    } else { // multi-elements IN expr has been processed with InPredicatePB
63
86
        if (op == "*=") {
64
1
            op = "=";
65
85
        } else if (op == "!*=") {
66
1
            op = "!=";
67
1
        }
68
86
        condition_str = condition.column_name + op + "'" + condition.condition_values[0] + "'";
69
86
    }
70
87
    return condition_str;
71
87
}
72
73
// make operators from FE adaptive to BE
74
87
std::string trans_op(const std::string& opt) {
75
87
    std::string op = string(opt);
76
87
    if (op == "<") {
77
50
        op += "<";
78
50
    } else if (op == ">") {
79
3
        op += ">";
80
3
    }
81
87
    if ("IS" != op) {
82
86
        if (op == "*=") {
83
1
            op = "=";
84
85
        } else if (op == "!*=") {
85
1
            op = "!=";
86
1
        }
87
86
    }
88
87
    return op;
89
87
}
90
91
Status DeleteHandler::generate_delete_predicate(const TabletSchema& schema,
92
                                                const std::vector<TCondition>& conditions,
93
97
                                                DeletePredicatePB* del_pred) {
94
97
    DBUG_EXECUTE_IF("DeleteHandler::generate_delete_predicate.inject_failure", {
95
97
        return Status::Error<false>(dp->param<int>("error_code"),
96
97
                                    dp->param<std::string>("error_msg"));
97
97
    })
98
97
    if (conditions.empty()) {
99
1
        return Status::Error<ErrorCode::INVALID_ARGUMENT>(
100
1
                "invalid parameters for store_cond. condition_size={}", conditions.size());
101
1
    }
102
103
    // Check whether the delete condition meets the requirements
104
113
    for (const TCondition& condition : conditions) {
105
113
        RETURN_IF_ERROR(check_condition_valid(schema, condition));
106
113
    }
107
108
    // Store delete condition
109
88
    for (const TCondition& condition : conditions) {
110
88
        if (condition.condition_values.size() > 1) {
111
1
            InPredicatePB* in_pred = del_pred->add_in_predicates();
112
1
            if (condition.__isset.column_unique_id) {
113
0
                in_pred->set_column_unique_id(condition.column_unique_id);
114
0
            }
115
1
            in_pred->set_column_name(condition.column_name);
116
1
            bool is_not_in = condition.condition_op == "!*=";
117
1
            in_pred->set_is_not_in(is_not_in);
118
2
            for (const auto& condition_value : condition.condition_values) {
119
2
                in_pred->add_values(condition_value);
120
2
            }
121
122
1
            LOG(INFO) << "store one sub-delete condition. condition name=" << in_pred->column_name()
123
1
                      << "condition size=" << in_pred->values().size();
124
87
        } else {
125
            // write sub predicate v1 for compactbility
126
87
            std::string condition_str = construct_sub_predicate(condition);
127
87
            VLOG_NOTICE << __PRETTY_FUNCTION__ << " condition_str: " << condition_str;
128
87
            del_pred->add_sub_predicates(condition_str);
129
87
            DeleteSubPredicatePB* sub_predicate = del_pred->add_sub_predicates_v2();
130
87
            if (condition.__isset.column_unique_id) {
131
                // only light schema change capable table set this field
132
0
                sub_predicate->set_column_unique_id(condition.column_unique_id);
133
87
            } else if (TCondition tmp; !DeleteHandler::parse_condition(condition_str, &tmp)) {
134
                // for non light shema change tables, check regex match for condition str
135
0
                LOG(WARNING) << "failed to parse condition_str, condtion="
136
0
                             << ThriftDebugString(condition);
137
0
                return Status::Error<ErrorCode::INVALID_ARGUMENT>(
138
0
                        "failed to parse condition_str, condtion={}", ThriftDebugString(condition));
139
0
            }
140
141
87
            sub_predicate->set_column_name(condition.column_name);
142
87
            sub_predicate->set_op(trans_op(condition.condition_op));
143
87
            sub_predicate->set_cond_value(condition.condition_values[0]);
144
87
            LOG(INFO) << "store one sub-delete condition. condition="
145
87
                      << fmt::format(" {} {} {}", condition.column_name, condition.condition_op,
146
87
                                     condition.condition_values[0]);
147
87
        }
148
88
    }
149
71
    del_pred->set_version(-1);
150
151
71
    return Status::OK();
152
71
}
153
154
void DeleteHandler::convert_to_sub_pred_v2(DeletePredicatePB* delete_pred,
155
0
                                           TabletSchemaSPtr schema) {
156
0
    if (!delete_pred->sub_predicates().empty() && delete_pred->sub_predicates_v2().empty()) {
157
0
        for (const auto& condition_str : delete_pred->sub_predicates()) {
158
0
            auto* sub_pred = delete_pred->add_sub_predicates_v2();
159
0
            TCondition condition;
160
0
            static_cast<void>(parse_condition(condition_str, &condition));
161
0
            sub_pred->set_column_unique_id(schema->column(condition.column_name).unique_id());
162
0
            sub_pred->set_column_name(condition.column_name);
163
0
            sub_pred->set_op(condition.condition_op);
164
0
            sub_pred->set_cond_value(condition.condition_values[0]);
165
0
        }
166
0
    }
167
168
0
    auto* in_pred_list = delete_pred->mutable_in_predicates();
169
0
    for (auto& in_pred : *in_pred_list) {
170
0
        in_pred.set_column_unique_id(schema->column(in_pred.column_name()).unique_id());
171
0
    }
172
0
}
173
174
bool DeleteHandler::is_condition_value_valid(const TabletColumn& column,
175
                                             const std::string& condition_op,
176
113
                                             const string& value_str) {
177
113
    if ("IS" == condition_op && ("NULL" == value_str || "NOT NULL" == value_str)) {
178
1
        return true;
179
1
    }
180
181
112
    FieldType field_type = column.type();
182
112
    switch (field_type) {
183
11
    case FieldType::OLAP_FIELD_TYPE_TINYINT:
184
11
        return valid_signed_number<int8_t>(value_str);
185
13
    case FieldType::OLAP_FIELD_TYPE_SMALLINT:
186
13
        return valid_signed_number<int16_t>(value_str);
187
54
    case FieldType::OLAP_FIELD_TYPE_INT:
188
54
        return valid_signed_number<int32_t>(value_str);
189
5
    case FieldType::OLAP_FIELD_TYPE_BIGINT:
190
5
        return valid_signed_number<int64_t>(value_str);
191
4
    case FieldType::OLAP_FIELD_TYPE_LARGEINT:
192
4
        return valid_signed_number<int128_t>(value_str);
193
0
    case FieldType::OLAP_FIELD_TYPE_UNSIGNED_TINYINT:
194
0
        return valid_unsigned_number<uint8_t>(value_str);
195
0
    case FieldType::OLAP_FIELD_TYPE_UNSIGNED_SMALLINT:
196
0
        return valid_unsigned_number<uint16_t>(value_str);
197
0
    case FieldType::OLAP_FIELD_TYPE_UNSIGNED_INT:
198
0
        return valid_unsigned_number<uint32_t>(value_str);
199
0
    case FieldType::OLAP_FIELD_TYPE_UNSIGNED_BIGINT:
200
0
        return valid_unsigned_number<uint64_t>(value_str);
201
7
    case FieldType::OLAP_FIELD_TYPE_DECIMAL:
202
7
        return valid_decimal(value_str, column.precision(), column.frac());
203
0
    case FieldType::OLAP_FIELD_TYPE_DECIMAL32:
204
0
        return valid_decimal(value_str, column.precision(), column.frac());
205
0
    case FieldType::OLAP_FIELD_TYPE_DECIMAL64:
206
0
        return valid_decimal(value_str, column.precision(), column.frac());
207
0
    case FieldType::OLAP_FIELD_TYPE_DECIMAL128I:
208
0
        return valid_decimal(value_str, column.precision(), column.frac());
209
0
    case FieldType::OLAP_FIELD_TYPE_DECIMAL256:
210
0
        return valid_decimal(value_str, column.precision(), column.frac());
211
3
    case FieldType::OLAP_FIELD_TYPE_CHAR:
212
7
    case FieldType::OLAP_FIELD_TYPE_VARCHAR:
213
7
        return value_str.size() <= column.length();
214
0
    case FieldType::OLAP_FIELD_TYPE_STRING:
215
0
        return value_str.size() <= config::string_type_length_soft_limit_bytes;
216
5
    case FieldType::OLAP_FIELD_TYPE_DATE:
217
11
    case FieldType::OLAP_FIELD_TYPE_DATETIME:
218
11
    case FieldType::OLAP_FIELD_TYPE_DATEV2:
219
11
    case FieldType::OLAP_FIELD_TYPE_DATETIMEV2:
220
11
        return valid_datetime(value_str, column.frac());
221
0
    case FieldType::OLAP_FIELD_TYPE_BOOL:
222
0
        return valid_bool(value_str);
223
0
    case FieldType::OLAP_FIELD_TYPE_IPV4:
224
0
        return valid_ipv4(value_str);
225
0
    case FieldType::OLAP_FIELD_TYPE_IPV6:
226
0
        return valid_ipv6(value_str);
227
0
    default:
228
0
        LOG(WARNING) << "unknown field type. [type=" << int(field_type) << "]";
229
112
    }
230
0
    return false;
231
112
}
232
233
113
Status DeleteHandler::check_condition_valid(const TabletSchema& schema, const TCondition& cond) {
234
    // Check whether the column exists
235
113
    int32_t field_index = schema.field_index(cond.column_name);
236
113
    if (field_index < 0) {
237
1
        return Status::Error<ErrorCode::INVALID_ARGUMENT>("field is not existent. [field_index={}]",
238
1
                                                          field_index);
239
1
    }
240
241
    // Delete condition should only applied on key columns or duplicate key table, and
242
    // the condition column type should not be float or double.
243
112
    const TabletColumn& column = schema.column(field_index);
244
245
112
    if (column.type() == FieldType::OLAP_FIELD_TYPE_DOUBLE ||
246
112
        column.type() == FieldType::OLAP_FIELD_TYPE_FLOAT) {
247
0
        return Status::Error<ErrorCode::INVALID_ARGUMENT>("data type is float or double.");
248
0
    }
249
250
    // Check operator and operands size are matched.
251
112
    if ("*=" != cond.condition_op && "!*=" != cond.condition_op &&
252
112
        cond.condition_values.size() != 1) {
253
0
        return Status::Error<ErrorCode::INVALID_ARGUMENT>("invalid condition value size. [size={}]",
254
0
                                                          cond.condition_values.size());
255
0
    }
256
257
    // Check each operand is valid
258
113
    for (const auto& condition_value : cond.condition_values) {
259
113
        if (!is_condition_value_valid(column, cond.condition_op, condition_value)) {
260
24
            return Status::Error<ErrorCode::INVALID_ARGUMENT>("invalid condition value. [value={}]",
261
24
                                                              condition_value);
262
24
        }
263
113
    }
264
265
88
    if (!cond.__isset.column_unique_id) {
266
88
        LOG(WARNING) << "column=" << cond.column_name
267
88
                     << " in predicate does not have uid, table id=" << schema.table_id();
268
        // TODO(tsy): make it fail here after FE forbidding hard-link-schema-change
269
88
        return Status::OK();
270
88
    }
271
0
    if (schema.field_index(cond.column_unique_id) == -1) {
272
0
        const auto& err_msg =
273
0
                fmt::format("column id does not exists in table={}, schema version={},",
274
0
                            schema.table_id(), schema.schema_version());
275
0
        return Status::Error<ErrorCode::INVALID_ARGUMENT>(err_msg);
276
0
    }
277
0
    if (!iequal(schema.column_by_uid(cond.column_unique_id).name(), cond.column_name)) {
278
0
        const auto& err_msg = fmt::format(
279
0
                "colum name={} does not belongs to column uid={}, which "
280
0
                "column name={}, "
281
0
                "delete_cond.column_name ={}",
282
0
                cond.column_name, cond.column_unique_id,
283
0
                schema.column_by_uid(cond.column_unique_id).name(), cond.column_name);
284
0
        return Status::Error<ErrorCode::INVALID_ARGUMENT>(err_msg);
285
0
    }
286
287
0
    return Status::OK();
288
0
}
289
290
90
Status DeleteHandler::parse_condition(const DeleteSubPredicatePB& sub_cond, TCondition* condition) {
291
90
    if (!sub_cond.has_column_name() || !sub_cond.has_op() || !sub_cond.has_cond_value()) {
292
0
        return Status::Error<ErrorCode::INVALID_ARGUMENT>(
293
0
                "fail to parse condition. condition={} {} {}", sub_cond.column_name(),
294
0
                sub_cond.op(), sub_cond.cond_value());
295
0
    }
296
90
    if (sub_cond.has_column_unique_id()) {
297
0
        condition->column_unique_id = sub_cond.column_unique_id();
298
0
    }
299
90
    condition->column_name = sub_cond.column_name();
300
90
    condition->condition_op = sub_cond.op();
301
90
    condition->condition_values.push_back(sub_cond.cond_value());
302
90
    return Status::OK();
303
90
}
304
305
// clang-format off
306
// Condition string format, the format is (column_name)(op)(value)
307
// eg: condition_str="c1 = 1597751948193618247 and length(source)<1;\n;\n"
308
// column_name: matches "c1", must include FeNameFormat.java COLUMN_NAME_REGEX
309
//              and compactible with any the lagacy
310
// operator: matches "="
311
// value: matches "1597751948193618247  and length(source)<1;\n;\n"
312
//
313
// For more info, see DeleteHandler::construct_sub_predicates
314
// FIXME(gavin): support unicode. And this is a tricky implementation, it should
315
//               not be the final resolution, refactor it.
316
const char* const CONDITION_STR_PATTERN =
317
    // .----------------- column-name ----------------.   .----------------------- operator ------------------------.   .------------ value ----------.
318
    R"(([_a-zA-Z@0-9\s/][.a-zA-Z0-9_+-/?@#$%^&*"\s,:]*)\s*((?:=)|(?:!=)|(?:>>)|(?:<<)|(?:>=)|(?:<=)|(?:\*=)|(?: IS ))\s*('((?:[\s\S]+)?)'|(?:[\s\S]+)?))";
319
    // '----------------- group 1 --------------------'   '--------------------- group 2 ---------------------------'   | '-- group 4--'              |
320
    //                                                         match any of: = != >> << >= <= *= " IS "                 '----------- group 3 ---------'
321
    //                                                                                                                   match **ANY THING** without(4)
322
    //                                                                                                                   or with(3) single quote
323
boost::regex DELETE_HANDLER_REGEX(CONDITION_STR_PATTERN);
324
// clang-format on
325
326
113
Status DeleteHandler::parse_condition(const std::string& condition_str, TCondition* condition) {
327
113
    bool matched = false;
328
113
    boost::smatch what;
329
113
    try {
330
113
        VLOG_NOTICE << "condition_str: " << condition_str;
331
113
        matched = boost::regex_match(condition_str, what, DELETE_HANDLER_REGEX) &&
332
113
                  condition_str.size() == what[0].str().size(); // exact match
333
113
    } catch (boost::regex_error& e) {
334
0
        VLOG_NOTICE << "fail to parse expr. [expr=" << condition_str << "; error=" << e.what()
335
0
                    << "]";
336
0
    }
337
113
    if (!matched) {
338
1
        return Status::Error<ErrorCode::INVALID_ARGUMENT>("fail to sub condition. condition={}",
339
1
                                                          condition_str);
340
1
    }
341
342
112
    condition->column_name = what[1].str();
343
112
    condition->condition_op = what[2].str() == " IS " ? "IS" : what[2].str();
344
    // match string with single quotes, a = b  or a = 'b'
345
112
    condition->condition_values.push_back(what[3 + !!what[4].matched].str());
346
112
    VLOG_NOTICE << "parsed condition_str: col_name={" << condition->column_name << "} op={"
347
0
                << condition->condition_op << "} val={" << condition->condition_values.back()
348
0
                << "}";
349
112
    return Status::OK();
350
113
}
351
352
template <typename SubPredType>
353
    requires(std::is_same_v<SubPredType, DeleteSubPredicatePB> or
354
             std::is_same_v<SubPredType, std::string>)
355
Status DeleteHandler::_parse_column_pred(TabletSchemaSPtr complete_schema,
356
                                         TabletSchemaSPtr delete_pred_related_schema,
357
                                         const RepeatedPtrField<SubPredType>& sub_pred_list,
358
89
                                         DeleteConditions* delete_conditions) {
359
100
    for (const auto& sub_predicate : sub_pred_list) {
360
100
        TCondition condition;
361
100
        RETURN_IF_ERROR(parse_condition(sub_predicate, &condition));
362
100
        int32_t col_unique_id = -1;
363
100
        if constexpr (std::is_same_v<SubPredType, DeleteSubPredicatePB>) {
364
90
            if (sub_predicate.has_column_unique_id()) [[likely]] {
365
0
                col_unique_id = sub_predicate.column_unique_id();
366
0
            }
367
90
        }
368
100
        if (col_unique_id < 0) {
369
100
            col_unique_id = delete_pred_related_schema->column(condition.column_name).unique_id();
370
100
        }
371
100
        condition.__set_column_unique_id(col_unique_id);
372
100
        const auto& column = complete_schema->column_by_uid(col_unique_id);
373
100
        uint32_t index = complete_schema->field_index(col_unique_id);
374
100
        auto* predicate =
375
100
                parse_to_predicate(column, index, condition, _predicate_arena.get(), true);
376
100
        if (predicate != nullptr) {
377
100
            delete_conditions->column_predicate_vec.push_back(predicate);
378
100
        }
379
100
    }
380
89
    return Status::OK();
381
89
}
_ZN5doris13DeleteHandler18_parse_column_predINS_20DeleteSubPredicatePBEEENS_6StatusESt10shared_ptrINS_12TabletSchemaEES6_RKN6google8protobuf16RepeatedPtrFieldIT_EEPNS_16DeleteConditionsE
Line
Count
Source
358
85
                                         DeleteConditions* delete_conditions) {
359
90
    for (const auto& sub_predicate : sub_pred_list) {
360
90
        TCondition condition;
361
90
        RETURN_IF_ERROR(parse_condition(sub_predicate, &condition));
362
90
        int32_t col_unique_id = -1;
363
90
        if constexpr (std::is_same_v<SubPredType, DeleteSubPredicatePB>) {
364
90
            if (sub_predicate.has_column_unique_id()) [[likely]] {
365
0
                col_unique_id = sub_predicate.column_unique_id();
366
0
            }
367
90
        }
368
90
        if (col_unique_id < 0) {
369
90
            col_unique_id = delete_pred_related_schema->column(condition.column_name).unique_id();
370
90
        }
371
90
        condition.__set_column_unique_id(col_unique_id);
372
90
        const auto& column = complete_schema->column_by_uid(col_unique_id);
373
90
        uint32_t index = complete_schema->field_index(col_unique_id);
374
90
        auto* predicate =
375
90
                parse_to_predicate(column, index, condition, _predicate_arena.get(), true);
376
90
        if (predicate != nullptr) {
377
90
            delete_conditions->column_predicate_vec.push_back(predicate);
378
90
        }
379
90
    }
380
85
    return Status::OK();
381
85
}
_ZN5doris13DeleteHandler18_parse_column_predINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEEENS_6StatusESt10shared_ptrINS_12TabletSchemaEESB_RKN6google8protobuf16RepeatedPtrFieldIT_EEPNS_16DeleteConditionsE
Line
Count
Source
358
4
                                         DeleteConditions* delete_conditions) {
359
10
    for (const auto& sub_predicate : sub_pred_list) {
360
10
        TCondition condition;
361
10
        RETURN_IF_ERROR(parse_condition(sub_predicate, &condition));
362
10
        int32_t col_unique_id = -1;
363
10
        if constexpr (std::is_same_v<SubPredType, DeleteSubPredicatePB>) {
364
10
            if (sub_predicate.has_column_unique_id()) [[likely]] {
365
10
                col_unique_id = sub_predicate.column_unique_id();
366
10
            }
367
10
        }
368
10
        if (col_unique_id < 0) {
369
10
            col_unique_id = delete_pred_related_schema->column(condition.column_name).unique_id();
370
10
        }
371
10
        condition.__set_column_unique_id(col_unique_id);
372
10
        const auto& column = complete_schema->column_by_uid(col_unique_id);
373
10
        uint32_t index = complete_schema->field_index(col_unique_id);
374
10
        auto* predicate =
375
10
                parse_to_predicate(column, index, condition, _predicate_arena.get(), true);
376
10
        if (predicate != nullptr) {
377
10
            delete_conditions->column_predicate_vec.push_back(predicate);
378
10
        }
379
10
    }
380
4
    return Status::OK();
381
4
}
382
383
template Status DeleteHandler::_parse_column_pred<DeleteSubPredicatePB>(
384
        TabletSchemaSPtr complete_schema, TabletSchemaSPtr delete_pred_related_schema,
385
        const ::google::protobuf::RepeatedPtrField<DeleteSubPredicatePB>& sub_pred_list,
386
        DeleteConditions* delete_conditions);
387
388
template Status DeleteHandler::_parse_column_pred<std::string>(
389
        TabletSchemaSPtr complete_schema, TabletSchemaSPtr delete_pred_related_schema,
390
        const ::google::protobuf::RepeatedPtrField<std::string>& sub_pred_list,
391
        DeleteConditions* delete_conditions);
392
393
Status DeleteHandler::init(TabletSchemaSPtr tablet_schema,
394
168
                           const std::vector<RowsetMetaSharedPtr>& delete_preds, int64_t version) {
395
168
    DCHECK(!_is_inited) << "reinitialize delete handler.";
396
168
    DCHECK(version >= 0) << "invalid parameters. version=" << version;
397
168
    _predicate_arena = std::make_unique<vectorized::Arena>();
398
399
168
    for (const auto& delete_pred : delete_preds) {
400
        // Skip the delete condition with large version
401
89
        if (delete_pred->version().first > version) {
402
0
            continue;
403
0
        }
404
        // Need the tablet schema at the delete condition to parse the accurate column
405
89
        const auto& delete_pred_related_schema = delete_pred->tablet_schema();
406
89
        const auto& delete_condition = delete_pred->delete_predicate();
407
89
        DeleteConditions temp;
408
89
        temp.filter_version = delete_pred->version().first;
409
89
        if (!delete_condition.sub_predicates_v2().empty()) {
410
85
            RETURN_IF_ERROR(_parse_column_pred(tablet_schema, delete_pred_related_schema,
411
85
                                               delete_condition.sub_predicates_v2(), &temp));
412
85
        } else {
413
            // make it compatible with the former versions
414
4
            RETURN_IF_ERROR(_parse_column_pred(tablet_schema, delete_pred_related_schema,
415
4
                                               delete_condition.sub_predicates(), &temp));
416
4
        }
417
89
        for (const auto& in_predicate : delete_condition.in_predicates()) {
418
0
            TCondition condition;
419
0
            condition.__set_column_name(in_predicate.column_name());
420
421
0
            int32_t col_unique_id = -1;
422
0
            if (in_predicate.has_column_unique_id()) {
423
0
                col_unique_id = in_predicate.column_unique_id();
424
0
            } else {
425
                // if upgrade from version 2.0.x, column_unique_id maybe not set
426
0
                col_unique_id =
427
0
                        delete_pred_related_schema->column(condition.column_name).unique_id();
428
0
            }
429
0
            if (col_unique_id == -1) {
430
0
                return Status::Error<ErrorCode::DELETE_INVALID_CONDITION>(
431
0
                        "cannot get column_unique_id for column {}", condition.column_name);
432
0
            }
433
0
            condition.__set_column_unique_id(col_unique_id);
434
435
0
            if (in_predicate.is_not_in()) {
436
0
                condition.__set_condition_op("!*=");
437
0
            } else {
438
0
                condition.__set_condition_op("*=");
439
0
            }
440
0
            for (const auto& value : in_predicate.values()) {
441
0
                condition.condition_values.push_back(value);
442
0
            }
443
0
            const auto& column = tablet_schema->column_by_uid(col_unique_id);
444
0
            uint32_t index = tablet_schema->field_index(col_unique_id);
445
0
            temp.column_predicate_vec.push_back(
446
0
                    parse_to_predicate(column, index, condition, _predicate_arena.get(), true));
447
0
        }
448
449
89
        _del_conds.emplace_back(std::move(temp));
450
89
    }
451
452
168
    _is_inited = true;
453
454
168
    return Status::OK();
455
168
}
456
457
169
DeleteHandler::~DeleteHandler() {
458
169
    if (!_is_inited) {
459
1
        return;
460
1
    }
461
462
168
    for (auto& cond : _del_conds) {
463
100
        for (const auto* pred : cond.column_predicate_vec) {
464
100
            delete pred;
465
100
        }
466
89
    }
467
468
168
    _del_conds.clear();
469
168
    _is_inited = false;
470
168
}
471
472
void DeleteHandler::get_delete_conditions_after_version(
473
        int64_t version, AndBlockColumnPredicate* and_block_column_predicate_ptr,
474
        std::unordered_map<int32_t, std::vector<const ColumnPredicate*>>*
475
421
                del_predicates_for_zone_map) const {
476
421
    for (const auto& del_cond : _del_conds) {
477
267
        if (del_cond.filter_version > version) {
478
            // now, only query support delete column predicate operator
479
190
            if (!del_cond.column_predicate_vec.empty()) {
480
190
                if (del_cond.column_predicate_vec.size() == 1) {
481
190
                    auto single_column_block_predicate = SingleColumnBlockPredicate::create_unique(
482
190
                            del_cond.column_predicate_vec[0]);
483
190
                    and_block_column_predicate_ptr->add_column_predicate(
484
190
                            std::move(single_column_block_predicate));
485
190
                    if (del_predicates_for_zone_map->count(
486
190
                                del_cond.column_predicate_vec[0]->column_id()) < 1) {
487
190
                        del_predicates_for_zone_map->insert(
488
190
                                {del_cond.column_predicate_vec[0]->column_id(),
489
190
                                 std::vector<const ColumnPredicate*> {}});
490
190
                    }
491
190
                    (*del_predicates_for_zone_map)[del_cond.column_predicate_vec[0]->column_id()]
492
190
                            .push_back(del_cond.column_predicate_vec[0]);
493
190
                } else {
494
0
                    auto or_column_predicate = OrBlockColumnPredicate::create_unique();
495
496
                    // build or_column_predicate
497
                    // when delete from where a = 1 and b = 2, we can not use del_predicates_for_zone_map to filter zone page,
498
                    // so here do not put predicate to del_predicates_for_zone_map,
499
                    // refer #17145 for more details.
500
                    // // TODO: need refactor design and code to use more version delete and more column delete to filter zone page.
501
0
                    std::for_each(del_cond.column_predicate_vec.cbegin(),
502
0
                                  del_cond.column_predicate_vec.cend(),
503
0
                                  [&or_column_predicate](const ColumnPredicate* predicate) {
504
0
                                      or_column_predicate->add_column_predicate(
505
0
                                              SingleColumnBlockPredicate::create_unique(predicate));
506
0
                                  });
507
0
                    and_block_column_predicate_ptr->add_column_predicate(
508
0
                            std::move(or_column_predicate));
509
0
                }
510
190
            }
511
190
        }
512
267
    }
513
421
}
514
515
} // namespace doris