Coverage Report

Created: 2025-07-27 01:30

/root/doris/be/src/exec/tablet_info.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 "exec/tablet_info.h"
19
20
#include <butil/logging.h>
21
#include <gen_cpp/Descriptors_types.h>
22
#include <gen_cpp/Exprs_types.h>
23
#include <gen_cpp/Partitions_types.h>
24
#include <gen_cpp/Types_types.h>
25
#include <gen_cpp/descriptors.pb.h>
26
#include <gen_cpp/olap_file.pb.h>
27
#include <glog/logging.h>
28
29
#include <algorithm>
30
#include <cstddef>
31
#include <cstdint>
32
#include <memory>
33
#include <ostream>
34
#include <string>
35
#include <tuple>
36
37
#include "common/exception.h"
38
#include "common/logging.h"
39
#include "common/status.h"
40
#include "olap/tablet_schema.h"
41
#include "runtime/define_primitive_type.h"
42
#include "runtime/descriptors.h"
43
#include "runtime/large_int_value.h"
44
#include "runtime/memory/mem_tracker.h"
45
#include "runtime/primitive_type.h"
46
#include "runtime/raw_value.h"
47
#include "runtime/types.h"
48
#include "util/string_parser.hpp"
49
#include "util/string_util.h"
50
#include "vec/columns/column.h"
51
// NOLINTNEXTLINE(unused-includes)
52
#include "vec/exprs/vexpr_context.h" // IWYU pragma: keep
53
#include "vec/exprs/vliteral.h"
54
#include "vec/runtime/vdatetime_value.h"
55
56
namespace doris {
57
58
32
void OlapTableIndexSchema::to_protobuf(POlapTableIndexSchema* pindex) const {
59
32
    pindex->set_id(index_id);
60
32
    pindex->set_schema_hash(schema_hash);
61
32
    for (auto* slot : slots) {
  Branch (61:21): [True: 0, False: 32]
62
0
        pindex->add_columns(slot->col_name());
63
0
    }
64
32
    for (auto* column : columns) {
  Branch (64:23): [True: 0, False: 32]
65
0
        column->to_schema_pb(pindex->add_columns_desc());
66
0
    }
67
32
    for (auto* index : indexes) {
  Branch (67:22): [True: 0, False: 32]
68
0
        index->to_schema_pb(pindex->add_indexes_desc());
69
0
    }
70
32
}
71
72
bool VOlapTablePartKeyComparator::operator()(const BlockRowWithIndicator& lhs,
73
0
                                             const BlockRowWithIndicator& rhs) const {
74
0
    vectorized::Block* l_block = std::get<0>(lhs);
75
0
    vectorized::Block* r_block = std::get<0>(rhs);
76
0
    int32_t l_row = std::get<1>(lhs);
77
0
    int32_t r_row = std::get<1>(rhs);
78
0
    bool l_use_new = std::get<2>(lhs);
79
0
    bool r_use_new = std::get<2>(rhs);
80
81
0
    VLOG_TRACE << '\n' << l_block->dump_data() << '\n' << r_block->dump_data();
Line
Count
Source
40
0
#define VLOG_TRACE VLOG(10)
82
83
0
    if (l_row == -1) {
  Branch (83:9): [True: 0, False: 0]
84
0
        return false;
85
0
    } else if (r_row == -1) {
  Branch (85:16): [True: 0, False: 0]
86
0
        return true;
87
0
    }
88
89
0
    if (_param_locs.empty()) { // no transform, use origin column
  Branch (89:9): [True: 0, False: 0]
90
0
        for (auto slot_loc : _slot_locs) {
  Branch (90:28): [True: 0, False: 0]
91
0
            auto res = l_block->get_by_position(slot_loc).column->compare_at(
92
0
                    l_row, r_row, *r_block->get_by_position(slot_loc).column, -1);
93
0
            if (res != 0) {
  Branch (93:17): [True: 0, False: 0]
94
0
                return res < 0;
95
0
            }
96
0
        }
97
0
    } else { // use transformed column to compare
98
0
        DCHECK(_slot_locs.size() == _param_locs.size())
99
0
                << _slot_locs.size() << ' ' << _param_locs.size();
100
101
0
        const std::vector<uint16_t>* l_index = l_use_new ? &_param_locs : &_slot_locs;
  Branch (101:48): [True: 0, False: 0]
102
0
        const std::vector<uint16_t>* r_index = r_use_new ? &_param_locs : &_slot_locs;
  Branch (102:48): [True: 0, False: 0]
103
104
0
        for (int i = 0; i < _slot_locs.size(); i++) {
  Branch (104:25): [True: 0, False: 0]
105
0
            vectorized::ColumnPtr l_col = l_block->get_by_position((*l_index)[i]).column;
106
0
            vectorized::ColumnPtr r_col = r_block->get_by_position((*r_index)[i]).column;
107
108
0
            auto res = l_col->compare_at(l_row, r_row, *r_col, -1);
109
0
            if (res != 0) {
  Branch (109:17): [True: 0, False: 0]
110
0
                return res < 0;
111
0
            }
112
0
        }
113
0
    }
114
115
    // equal, return false
116
0
    return false;
117
0
}
118
119
14
Status OlapTableSchemaParam::init(const POlapTableSchemaParam& pschema) {
120
14
    _db_id = pschema.db_id();
121
14
    _table_id = pschema.table_id();
122
14
    _version = pschema.version();
123
14
    if (pschema.has_unique_key_update_mode()) {
  Branch (123:9): [True: 14, False: 0]
124
14
        _unique_key_update_mode = pschema.unique_key_update_mode();
125
14
        if (pschema.has_sequence_map_col_unique_id()) {
  Branch (125:13): [True: 14, False: 0]
126
14
            _sequence_map_col_uid = pschema.sequence_map_col_unique_id();
127
14
        }
128
14
    } else {
129
        // for backward compatibility
130
0
        if (pschema.has_partial_update() && pschema.partial_update()) {
  Branch (130:13): [True: 0, False: 0]
  Branch (130:45): [True: 0, False: 0]
131
0
            _unique_key_update_mode = UniqueKeyUpdateModePB::UPDATE_FIXED_COLUMNS;
132
0
        } else {
133
0
            _unique_key_update_mode = UniqueKeyUpdateModePB::UPSERT;
134
0
        }
135
0
    }
136
14
    _is_strict_mode = pschema.is_strict_mode();
137
14
    if (_unique_key_update_mode == UniqueKeyUpdateModePB::UPDATE_FIXED_COLUMNS) {
  Branch (137:9): [True: 0, False: 14]
138
0
        _auto_increment_column = pschema.auto_increment_column();
139
0
        if (!_auto_increment_column.empty() && pschema.auto_increment_column_unique_id() == -1) {
  Branch (139:13): [True: 0, False: 0]
  Branch (139:48): [True: 0, False: 0]
140
0
            return Status::InternalError(
141
0
                    "Auto increment column id is not set in FE. Maybe FE is an older version "
142
0
                    "different from BE.");
143
0
        }
144
0
        _auto_increment_column_unique_id = pschema.auto_increment_column_unique_id();
145
0
    }
146
14
    if (_unique_key_update_mode != UniqueKeyUpdateModePB::UPSERT) {
  Branch (146:9): [True: 0, False: 14]
147
0
        if (pschema.has_partial_update_new_key_policy()) {
  Branch (147:13): [True: 0, False: 0]
148
0
            _partial_update_new_row_policy = pschema.partial_update_new_key_policy();
149
0
        }
150
0
    }
151
14
    _timestamp_ms = pschema.timestamp_ms();
152
14
    if (pschema.has_nano_seconds()) {
  Branch (152:9): [True: 14, False: 0]
153
14
        _nano_seconds = pschema.nano_seconds();
154
14
    }
155
14
    _timezone = pschema.timezone();
156
157
14
    for (const auto& col : pschema.partial_update_input_columns()) {
  Branch (157:26): [True: 0, False: 14]
158
0
        _partial_update_input_columns.insert(col);
159
0
    }
160
14
    std::unordered_map<std::string, SlotDescriptor*> slots_map;
161
162
14
    _tuple_desc = _obj_pool.add(new TupleDescriptor(pschema.tuple_desc()));
163
164
84
    for (const auto& p_slot_desc : pschema.slot_descs()) {
  Branch (164:34): [True: 84, False: 14]
165
84
        auto* slot_desc = _obj_pool.add(new SlotDescriptor(p_slot_desc));
166
84
        _tuple_desc->add_slot(slot_desc);
167
84
        string data_type;
168
84
        EnumToString(TPrimitiveType, to_thrift(slot_desc->col_type()), data_type);
Line
Count
Source
212
84
    do {                                                      \
213
84
        auto it = _##enum_type##_VALUES_TO_NAMES.find(index); \
214
84
        if (it == _##enum_type##_VALUES_TO_NAMES.end()) {     \
  Branch (214:13): [True: 0, False: 84]
215
0
            out = "NULL";                                     \
216
84
        } else {                                              \
217
84
            out = it->second;                                 \
218
84
        }                                                     \
219
84
    } while (0)
  Branch (219:14): [Folded - Ignored]
169
84
        std::string is_null_str = slot_desc->is_nullable() ? "true" : "false";
  Branch (169:35): [True: 84, False: 0]
170
84
        std::string data_type_str =
171
84
                std::to_string(int64_t(TabletColumn::get_field_type_by_string(data_type)));
172
84
        slots_map.emplace(to_lower(slot_desc->col_name()) + "+" + data_type_str + is_null_str,
173
84
                          slot_desc);
174
84
    }
175
176
28
    for (const auto& p_index : pschema.indexes()) {
  Branch (176:30): [True: 28, False: 14]
177
28
        auto* index = _obj_pool.add(new OlapTableIndexSchema());
178
28
        index->index_id = p_index.id();
179
28
        index->schema_hash = p_index.schema_hash();
180
28
        for (const auto& pcolumn_desc : p_index.columns_desc()) {
  Branch (180:39): [True: 0, False: 28]
181
0
            if (_unique_key_update_mode != UniqueKeyUpdateModePB::UPDATE_FIXED_COLUMNS ||
  Branch (181:17): [True: 0, False: 0]
182
0
                _partial_update_input_columns.contains(pcolumn_desc.name())) {
  Branch (182:17): [True: 0, False: 0]
183
0
                std::string is_null_str = pcolumn_desc.is_nullable() ? "true" : "false";
  Branch (183:43): [True: 0, False: 0]
184
0
                std::string data_type_str = std::to_string(
185
0
                        int64_t(TabletColumn::get_field_type_by_string(pcolumn_desc.type())));
186
0
                auto it = slots_map.find(to_lower(pcolumn_desc.name()) + "+" + data_type_str +
187
0
                                         is_null_str);
188
0
                if (it == std::end(slots_map)) {
  Branch (188:21): [True: 0, False: 0]
189
0
                    std::string keys {};
190
0
                    for (const auto& [key, _] : slots_map) {
  Branch (190:47): [True: 0, False: 0]
191
0
                        keys += fmt::format("{},", key);
192
0
                    }
193
0
                    LOG_EVERY_SECOND(WARNING) << fmt::format(
194
0
                            "[OlapTableSchemaParam::init(const POlapTableSchemaParam& pschema)]: "
195
0
                            "unknown index column, column={}, type={}, data_type_str={}, "
196
0
                            "is_null_str={}, slots_map.keys()=[{}], {}\npschema={}",
197
0
                            pcolumn_desc.name(), pcolumn_desc.type(), data_type_str, is_null_str,
198
0
                            keys, debug_string(), pschema.ShortDebugString());
199
200
0
                    return Status::InternalError("unknown index column, column={}, type={}",
201
0
                                                 pcolumn_desc.name(), pcolumn_desc.type());
202
0
                }
203
0
                index->slots.emplace_back(it->second);
204
0
            }
205
0
            TabletColumn* tc = _obj_pool.add(new TabletColumn());
206
0
            tc->init_from_pb(pcolumn_desc);
207
0
            index->columns.emplace_back(tc);
208
0
        }
209
28
        for (const auto& pindex_desc : p_index.indexes_desc()) {
  Branch (209:38): [True: 0, False: 28]
210
0
            TabletIndex* ti = _obj_pool.add(new TabletIndex());
211
0
            ti->init_from_pb(pindex_desc);
212
0
            index->indexes.emplace_back(ti);
213
0
        }
214
28
        _indexes.emplace_back(index);
215
28
    }
216
217
14
    std::sort(_indexes.begin(), _indexes.end(),
218
28
              [](const OlapTableIndexSchema* lhs, const OlapTableIndexSchema* rhs) {
219
28
                  return lhs->index_id < rhs->index_id;
220
28
              });
221
14
    return Status::OK();
222
14
}
223
224
16
Status OlapTableSchemaParam::init_unique_key_update_mode(const TOlapTableSchemaParam& tschema) {
225
16
    if (tschema.__isset.unique_key_update_mode) {
  Branch (225:9): [True: 16, False: 0]
226
16
        switch (tschema.unique_key_update_mode) {
227
16
        case doris::TUniqueKeyUpdateMode::UPSERT: {
  Branch (227:9): [True: 16, False: 0]
228
16
            _unique_key_update_mode = UniqueKeyUpdateModePB::UPSERT;
229
16
            break;
230
0
        }
231
0
        case doris::TUniqueKeyUpdateMode::UPDATE_FIXED_COLUMNS: {
  Branch (231:9): [True: 0, False: 16]
232
0
            _unique_key_update_mode = UniqueKeyUpdateModePB::UPDATE_FIXED_COLUMNS;
233
0
            break;
234
0
        }
235
0
        case doris::TUniqueKeyUpdateMode::UPDATE_FLEXIBLE_COLUMNS: {
  Branch (235:9): [True: 0, False: 16]
236
0
            _unique_key_update_mode = UniqueKeyUpdateModePB::UPDATE_FLEXIBLE_COLUMNS;
237
0
            break;
238
0
        }
239
0
        default: {
  Branch (239:9): [True: 0, False: 16]
240
0
            return Status::InternalError(
241
0
                    "Unknown unique_key_update_mode: {}, should be one of "
242
0
                    "UPSERT/UPDATE_FIXED_COLUMNS/UPDATE_FLEXIBLE_COLUMNS",
243
0
                    tschema.unique_key_update_mode);
244
0
        }
245
16
        }
246
16
        if (tschema.__isset.sequence_map_col_unique_id) {
  Branch (246:13): [True: 16, False: 0]
247
16
            _sequence_map_col_uid = tschema.sequence_map_col_unique_id;
248
16
        }
249
16
    } else {
250
        // for backward compatibility
251
0
        if (tschema.__isset.is_partial_update && tschema.is_partial_update) {
  Branch (251:13): [True: 0, False: 0]
  Branch (251:50): [True: 0, False: 0]
252
0
            _unique_key_update_mode = UniqueKeyUpdateModePB::UPDATE_FIXED_COLUMNS;
253
0
        } else {
254
0
            _unique_key_update_mode = UniqueKeyUpdateModePB::UPSERT;
255
0
        }
256
0
    }
257
16
    return Status::OK();
258
16
}
259
260
16
Status OlapTableSchemaParam::init(const TOlapTableSchemaParam& tschema) {
261
16
    _db_id = tschema.db_id;
262
16
    _table_id = tschema.table_id;
263
16
    _version = tschema.version;
264
16
    RETURN_IF_ERROR(init_unique_key_update_mode(tschema));
265
16
    if (tschema.__isset.is_strict_mode) {
  Branch (265:9): [True: 16, False: 0]
266
16
        _is_strict_mode = tschema.is_strict_mode;
267
16
    }
268
16
    if (_unique_key_update_mode == UniqueKeyUpdateModePB::UPDATE_FIXED_COLUMNS) {
  Branch (268:9): [True: 0, False: 16]
269
0
        _auto_increment_column = tschema.auto_increment_column;
270
0
        if (!_auto_increment_column.empty() && tschema.auto_increment_column_unique_id == -1) {
  Branch (270:13): [True: 0, False: 0]
  Branch (270:48): [True: 0, False: 0]
271
0
            return Status::InternalError(
272
0
                    "Auto increment column id is not set in FE. Maybe FE is an older version "
273
0
                    "different from BE.");
274
0
        }
275
0
        _auto_increment_column_unique_id = tschema.auto_increment_column_unique_id;
276
0
    }
277
278
16
    if (_unique_key_update_mode != UniqueKeyUpdateModePB::UPSERT) {
  Branch (278:9): [True: 0, False: 16]
279
0
        if (tschema.__isset.partial_update_new_key_policy) {
  Branch (279:13): [True: 0, False: 0]
280
0
            switch (tschema.partial_update_new_key_policy) {
281
0
            case doris::TPartialUpdateNewRowPolicy::APPEND: {
  Branch (281:13): [True: 0, False: 0]
282
0
                _partial_update_new_row_policy = PartialUpdateNewRowPolicyPB::APPEND;
283
0
                break;
284
0
            }
285
0
            case doris::TPartialUpdateNewRowPolicy::ERROR: {
  Branch (285:13): [True: 0, False: 0]
286
0
                _partial_update_new_row_policy = PartialUpdateNewRowPolicyPB::ERROR;
287
0
                break;
288
0
            }
289
0
            default: {
  Branch (289:13): [True: 0, False: 0]
290
0
                return Status::InvalidArgument(
291
0
                        "Unknown partial_update_new_key_behavior: {}, should be one of "
292
0
                        "'APPEND' or 'ERROR'",
293
0
                        tschema.partial_update_new_key_policy);
294
0
            }
295
0
            }
296
0
        }
297
0
    }
298
299
16
    for (const auto& tcolumn : tschema.partial_update_input_columns) {
  Branch (299:30): [True: 0, False: 16]
300
0
        _partial_update_input_columns.insert(tcolumn);
301
0
    }
302
16
    std::unordered_map<std::string, SlotDescriptor*> slots_map;
303
16
    _tuple_desc = _obj_pool.add(new TupleDescriptor(tschema.tuple_desc));
304
96
    for (const auto& t_slot_desc : tschema.slot_descs) {
  Branch (304:34): [True: 96, False: 16]
305
96
        auto* slot_desc = _obj_pool.add(new SlotDescriptor(t_slot_desc));
306
96
        _tuple_desc->add_slot(slot_desc);
307
96
        std::string is_null_str = slot_desc->is_nullable() ? "true" : "false";
  Branch (307:35): [True: 96, False: 0]
308
96
        std::string data_type_str = std::to_string(int64_t(slot_desc->col_type()));
309
96
        slots_map.emplace(to_lower(slot_desc->col_name()) + "+" + data_type_str + is_null_str,
310
96
                          slot_desc);
311
96
    }
312
313
32
    for (const auto& t_index : tschema.indexes) {
  Branch (313:30): [True: 32, False: 16]
314
32
        std::unordered_map<std::string, int32_t> index_slots_map;
315
32
        auto* index = _obj_pool.add(new OlapTableIndexSchema());
316
32
        index->index_id = t_index.id;
317
32
        index->schema_hash = t_index.schema_hash;
318
32
        for (const auto& tcolumn_desc : t_index.columns_desc) {
  Branch (318:39): [True: 0, False: 32]
319
0
            if (_unique_key_update_mode != UniqueKeyUpdateModePB::UPDATE_FIXED_COLUMNS ||
  Branch (319:17): [True: 0, False: 0]
320
0
                _partial_update_input_columns.contains(tcolumn_desc.column_name)) {
  Branch (320:17): [True: 0, False: 0]
321
0
                std::string is_null_str = tcolumn_desc.is_allow_null ? "true" : "false";
  Branch (321:43): [True: 0, False: 0]
322
0
                std::string data_type_str =
323
0
                        std::to_string(int64_t(thrift_to_type(tcolumn_desc.column_type.type)));
324
0
                auto it = slots_map.find(to_lower(tcolumn_desc.column_name) + "+" + data_type_str +
325
0
                                         is_null_str);
326
0
                if (it == slots_map.end()) {
  Branch (326:21): [True: 0, False: 0]
327
0
                    std::stringstream ss;
328
0
                    ss << tschema;
329
0
                    std::string keys {};
330
0
                    for (const auto& [key, _] : slots_map) {
  Branch (330:47): [True: 0, False: 0]
331
0
                        keys += fmt::format("{},", key);
332
0
                    }
333
0
                    LOG_EVERY_SECOND(WARNING) << fmt::format(
334
0
                            "[OlapTableSchemaParam::init(const TOlapTableSchemaParam& tschema)]: "
335
0
                            "unknown index column, column={}, type={}, data_type_str={}, "
336
0
                            "is_null_str={}, slots_map.keys()=[{}], {}\ntschema={}",
337
0
                            tcolumn_desc.column_name, tcolumn_desc.column_type.type, data_type_str,
338
0
                            is_null_str, keys, debug_string(), ss.str());
339
0
                    return Status::InternalError("unknown index column, column={}, type={}",
340
0
                                                 tcolumn_desc.column_name,
341
0
                                                 tcolumn_desc.column_type.type);
342
0
                }
343
0
                index->slots.emplace_back(it->second);
344
0
            }
345
0
            index_slots_map.emplace(to_lower(tcolumn_desc.column_name), tcolumn_desc.col_unique_id);
346
0
            TabletColumn* tc = _obj_pool.add(new TabletColumn());
347
0
            tc->init_from_thrift(tcolumn_desc);
348
0
            index->columns.emplace_back(tc);
349
0
        }
350
32
        if (t_index.__isset.indexes_desc) {
  Branch (350:13): [True: 0, False: 32]
351
0
            for (const auto& tindex_desc : t_index.indexes_desc) {
  Branch (351:42): [True: 0, False: 0]
352
0
                std::vector<int32_t> column_unique_ids(tindex_desc.columns.size());
353
0
                for (size_t i = 0; i < tindex_desc.columns.size(); i++) {
  Branch (353:36): [True: 0, False: 0]
354
0
                    auto it = index_slots_map.find(to_lower(tindex_desc.columns[i]));
355
0
                    if (it != index_slots_map.end()) {
  Branch (355:25): [True: 0, False: 0]
356
0
                        column_unique_ids[i] = it->second;
357
0
                    }
358
0
                }
359
0
                TabletIndex* ti = _obj_pool.add(new TabletIndex());
360
0
                ti->init_from_thrift(tindex_desc, column_unique_ids);
361
0
                index->indexes.emplace_back(ti);
362
0
            }
363
0
        }
364
32
        if (t_index.__isset.where_clause) {
  Branch (364:13): [True: 0, False: 32]
365
0
            RETURN_IF_ERROR(
366
0
                    vectorized::VExpr::create_expr_tree(t_index.where_clause, index->where_clause));
367
0
        }
368
32
        _indexes.emplace_back(index);
369
32
    }
370
371
16
    std::sort(_indexes.begin(), _indexes.end(),
372
32
              [](const OlapTableIndexSchema* lhs, const OlapTableIndexSchema* rhs) {
373
32
                  return lhs->index_id < rhs->index_id;
374
32
              });
375
16
    return Status::OK();
376
16
}
377
378
16
void OlapTableSchemaParam::to_protobuf(POlapTableSchemaParam* pschema) const {
379
16
    pschema->set_db_id(_db_id);
380
16
    pschema->set_table_id(_table_id);
381
16
    pschema->set_version(_version);
382
16
    pschema->set_unique_key_update_mode(_unique_key_update_mode);
383
16
    if (_unique_key_update_mode == UniqueKeyUpdateModePB::UPDATE_FIXED_COLUMNS) {
  Branch (383:9): [True: 0, False: 16]
384
        // for backward compatibility
385
0
        pschema->set_partial_update(true);
386
0
    }
387
16
    pschema->set_partial_update_new_key_policy(_partial_update_new_row_policy);
388
16
    pschema->set_is_strict_mode(_is_strict_mode);
389
16
    pschema->set_auto_increment_column(_auto_increment_column);
390
16
    pschema->set_auto_increment_column_unique_id(_auto_increment_column_unique_id);
391
16
    pschema->set_timestamp_ms(_timestamp_ms);
392
16
    pschema->set_timezone(_timezone);
393
16
    pschema->set_nano_seconds(_nano_seconds);
394
16
    pschema->set_sequence_map_col_unique_id(_sequence_map_col_uid);
395
16
    for (auto col : _partial_update_input_columns) {
  Branch (395:19): [True: 0, False: 16]
396
0
        *pschema->add_partial_update_input_columns() = col;
397
0
    }
398
16
    _tuple_desc->to_protobuf(pschema->mutable_tuple_desc());
399
96
    for (auto* slot : _tuple_desc->slots()) {
  Branch (399:21): [True: 96, False: 16]
400
96
        slot->to_protobuf(pschema->add_slot_descs());
401
96
    }
402
32
    for (auto* index : _indexes) {
  Branch (402:22): [True: 32, False: 16]
403
32
        index->to_protobuf(pschema->add_indexes());
404
32
    }
405
16
}
406
407
0
std::string OlapTableSchemaParam::debug_string() const {
408
0
    std::stringstream ss;
409
0
    ss << "tuple_desc=" << _tuple_desc->debug_string();
410
0
    return ss.str();
411
0
}
412
413
VOlapTablePartitionParam::VOlapTablePartitionParam(std::shared_ptr<OlapTableSchemaParam>& schema,
414
                                                   const TOlapTablePartitionParam& t_param)
415
        : _schema(schema),
416
          _t_param(t_param),
417
          _slots(_schema->tuple_desc()->slots()),
418
          _mem_tracker(std::make_unique<MemTracker>("OlapTablePartitionParam")),
419
0
          _part_type(t_param.partition_type) {
420
0
    if (t_param.__isset.enable_automatic_partition && t_param.enable_automatic_partition) {
  Branch (420:9): [True: 0, False: 0]
  Branch (420:55): [True: 0, False: 0]
421
0
        _is_auto_partition = true;
422
0
        auto size = t_param.partition_function_exprs.size();
423
0
        _part_func_ctx.resize(size);
424
0
        _partition_function.resize(size);
425
0
        DCHECK((t_param.partition_type == TPartitionType::RANGE_PARTITIONED && size == 1) ||
426
0
               (t_param.partition_type == TPartitionType::LIST_PARTITIONED && size >= 1))
427
0
                << "now support only 1 partition column for auto range partitions. "
428
0
                << t_param.partition_type << " " << size;
429
0
        for (int i = 0; i < size; ++i) {
  Branch (429:25): [True: 0, False: 0]
430
0
            Status st = vectorized::VExpr::create_expr_tree(t_param.partition_function_exprs[i],
431
0
                                                            _part_func_ctx[i]);
432
0
            if (!st.ok()) {
  Branch (432:17): [True: 0, False: 0]
433
0
                throw Exception(Status::InternalError("Partition function expr is not valid"),
434
0
                                "Partition function expr is not valid");
435
0
            }
436
0
            _partition_function[i] = _part_func_ctx[i]->root();
437
0
        }
438
0
    }
439
440
0
    if (t_param.__isset.enable_auto_detect_overwrite && t_param.enable_auto_detect_overwrite) {
  Branch (440:9): [True: 0, False: 0]
  Branch (440:57): [True: 0, False: 0]
441
0
        _is_auto_detect_overwrite = true;
442
0
        DCHECK(t_param.__isset.overwrite_group_id);
443
0
        _overwrite_group_id = t_param.overwrite_group_id;
444
0
    }
445
446
0
    if (_is_auto_partition) {
  Branch (446:9): [True: 0, False: 0]
447
        // the nullable mode depends on partition_exprs. not column slots. so use them.
448
0
        DCHECK(_partition_function.size() <= _slots.size())
449
0
                << _partition_function.size() << ", " << _slots.size();
450
451
        // suppose (k0, [k1], [k2]), so get [k1, 0], [k2, 1]
452
0
        std::map<std::string, int> partition_slots_map; // name to idx in part_exprs
453
0
        for (size_t i = 0; i < t_param.partition_columns.size(); i++) {
  Branch (453:28): [True: 0, False: 0]
454
0
            partition_slots_map.emplace(t_param.partition_columns[i], i);
455
0
        }
456
457
        // here we rely on the same order and number of the _part_funcs and _slots in the prefix
458
        // _part_block contains all slots of table.
459
0
        for (auto* slot : _slots) {
  Branch (459:25): [True: 0, False: 0]
460
            // try to replace with partition expr.
461
0
            if (auto it = partition_slots_map.find(slot->col_name());
462
0
                it != partition_slots_map.end()) { // it's a partition column slot
  Branch (462:17): [True: 0, False: 0]
463
0
                auto& expr_type = _partition_function[it->second]->data_type();
464
0
                _partition_block.insert({expr_type->create_column(), expr_type, slot->col_name()});
465
0
            } else {
466
0
                _partition_block.insert({slot->get_empty_mutable_column(),
467
0
                                         slot->get_data_type_ptr(), slot->col_name()});
468
0
            }
469
0
        }
470
0
        VLOG_TRACE << _partition_block.dump_structure();
Line
Count
Source
40
0
#define VLOG_TRACE VLOG(10)
471
0
    } else {
472
        // we insert all. but not all will be used. it will controlled by _partition_slot_locs
473
0
        for (auto* slot : _slots) {
  Branch (473:25): [True: 0, False: 0]
474
0
            _partition_block.insert({slot->get_empty_mutable_column(), slot->get_data_type_ptr(),
475
0
                                     slot->col_name()});
476
0
        }
477
0
    }
478
0
}
479
480
0
VOlapTablePartitionParam::~VOlapTablePartitionParam() {
481
0
    _mem_tracker->release(_mem_usage);
482
0
}
483
484
0
Status VOlapTablePartitionParam::init() {
485
0
    std::vector<std::string> slot_column_names;
486
0
    for (auto* slot_desc : _schema->tuple_desc()->slots()) {
  Branch (486:26): [True: 0, False: 0]
487
0
        slot_column_names.emplace_back(slot_desc->col_name());
488
0
    }
489
490
0
    auto find_slot_locs = [&slot_column_names](const std::string& slot_name,
491
0
                                               std::vector<uint16_t>& locs,
492
0
                                               const std::string& column_type) {
493
0
        auto it = std::find(slot_column_names.begin(), slot_column_names.end(), slot_name);
494
0
        if (it == slot_column_names.end()) {
  Branch (494:13): [True: 0, False: 0]
495
0
            return Status::InternalError("{} column not found, column ={}", column_type, slot_name);
496
0
        }
497
0
        locs.emplace_back(it - slot_column_names.begin());
498
0
        return Status::OK();
499
0
    };
500
501
    // here we find the partition columns. others maybe non-partition columns/special columns.
502
0
    if (_t_param.__isset.partition_columns) {
  Branch (502:9): [True: 0, False: 0]
503
0
        for (auto& part_col : _t_param.partition_columns) {
  Branch (503:29): [True: 0, False: 0]
504
0
            RETURN_IF_ERROR(find_slot_locs(part_col, _partition_slot_locs, "partition"));
505
0
        }
506
0
    }
507
508
0
    _partitions_map = std::make_unique<
509
0
            std::map<BlockRowWithIndicator, VOlapTablePartition*, VOlapTablePartKeyComparator>>(
510
0
            VOlapTablePartKeyComparator(_partition_slot_locs, _transformed_slot_locs));
511
0
    if (_t_param.__isset.distributed_columns) {
  Branch (511:9): [True: 0, False: 0]
512
0
        for (auto& col : _t_param.distributed_columns) {
  Branch (512:24): [True: 0, False: 0]
513
0
            RETURN_IF_ERROR(find_slot_locs(col, _distributed_slot_locs, "distributed"));
514
0
        }
515
0
    }
516
517
    // for both auto/non-auto partition table.
518
0
    _is_in_partition = _part_type == TPartitionType::type::LIST_PARTITIONED;
519
520
    // initial partitions. if meet dummy partitions only for open BE nodes, not generate key of them for finding
521
0
    for (const auto& t_part : _t_param.partitions) {
  Branch (521:29): [True: 0, False: 0]
522
0
        VOlapTablePartition* part = nullptr;
523
0
        RETURN_IF_ERROR(generate_partition_from(t_part, part));
524
0
        _partitions.emplace_back(part);
525
526
0
        if (!_t_param.partitions_is_fake) {
  Branch (526:13): [True: 0, False: 0]
527
0
            if (_is_in_partition) {
  Branch (527:17): [True: 0, False: 0]
528
0
                for (auto& in_key : part->in_keys) {
  Branch (528:35): [True: 0, False: 0]
529
0
                    _partitions_map->emplace(std::tuple {in_key.first, in_key.second, false}, part);
530
0
                }
531
0
            } else {
532
0
                _partitions_map->emplace(
533
0
                        std::tuple {part->end_key.first, part->end_key.second, false}, part);
534
0
            }
535
0
        }
536
0
    }
537
538
0
    _mem_usage = _partition_block.allocated_bytes();
539
0
    _mem_tracker->consume(_mem_usage);
540
0
    return Status::OK();
541
0
}
542
543
bool VOlapTablePartitionParam::_part_contains(VOlapTablePartition* part,
544
0
                                              BlockRowWithIndicator key) const {
545
0
    VOlapTablePartKeyComparator comparator(_partition_slot_locs, _transformed_slot_locs);
546
    // we have used upper_bound to find to ensure key < part.right and this part is closest(right - key is min)
547
    // now we only have to check (key >= part.left). the comparator(a,b) means a < b, so we use anti
548
0
    return part->start_key.second == -1 /* spj: start_key.second == -1 means only single partition*/
  Branch (548:12): [True: 0, False: 0]
549
0
           || !comparator(key, std::tuple {part->start_key.first, part->start_key.second, false});
  Branch (549:15): [True: 0, False: 0]
550
0
}
551
552
// insert value into _partition_block's column
553
// NOLINTBEGIN(readability-function-size)
554
0
static Status _create_partition_key(const TExprNode& t_expr, BlockRow* part_key, uint16_t pos) {
555
0
    auto column = std::move(*part_key->first->get_by_position(pos).column).mutate();
556
    //TODO: use assert_cast before insert_data
557
0
    switch (t_expr.node_type) {
558
0
    case TExprNodeType::DATE_LITERAL: {
  Branch (558:5): [True: 0, False: 0]
559
0
        if (TypeDescriptor::from_thrift(t_expr.type).is_date_v2_type()) {
  Branch (559:13): [True: 0, False: 0]
560
0
            DateV2Value<DateV2ValueType> dt;
561
0
            if (!dt.from_date_str(t_expr.date_literal.value.c_str(),
  Branch (561:17): [True: 0, False: 0]
562
0
                                  t_expr.date_literal.value.size())) {
563
0
                std::stringstream ss;
564
0
                ss << "invalid date literal in partition column, date=" << t_expr.date_literal;
565
0
                return Status::InternalError(ss.str());
566
0
            }
567
0
            column->insert_data(reinterpret_cast<const char*>(&dt), 0);
568
0
        } else if (TypeDescriptor::from_thrift(t_expr.type).is_datetime_v2_type()) {
  Branch (568:20): [True: 0, False: 0]
569
0
            DateV2Value<DateTimeV2ValueType> dt;
570
0
            const int32_t scale =
571
0
                    t_expr.type.types.empty() ? -1 : t_expr.type.types.front().scalar_type.scale;
  Branch (571:21): [True: 0, False: 0]
572
0
            if (!dt.from_date_str(t_expr.date_literal.value.c_str(),
  Branch (572:17): [True: 0, False: 0]
573
0
                                  t_expr.date_literal.value.size(), scale)) {
574
0
                std::stringstream ss;
575
0
                ss << "invalid date literal in partition column, date=" << t_expr.date_literal;
576
0
                return Status::InternalError(ss.str());
577
0
            }
578
0
            column->insert_data(reinterpret_cast<const char*>(&dt), 0);
579
0
        } else {
580
0
            VecDateTimeValue dt;
581
0
            if (!dt.from_date_str(t_expr.date_literal.value.c_str(),
  Branch (581:17): [True: 0, False: 0]
582
0
                                  t_expr.date_literal.value.size())) {
583
0
                std::stringstream ss;
584
0
                ss << "invalid date literal in partition column, date=" << t_expr.date_literal;
585
0
                return Status::InternalError(ss.str());
586
0
            }
587
0
            column->insert_data(reinterpret_cast<const char*>(&dt), 0);
588
0
        }
589
0
        break;
590
0
    }
591
0
    case TExprNodeType::INT_LITERAL: {
  Branch (591:5): [True: 0, False: 0]
592
0
        switch (t_expr.type.types[0].scalar_type.type) {
593
0
        case TPrimitiveType::TINYINT: {
  Branch (593:9): [True: 0, False: 0]
594
0
            int8_t value = t_expr.int_literal.value;
595
0
            column->insert_data(reinterpret_cast<const char*>(&value), 0);
596
0
            break;
597
0
        }
598
0
        case TPrimitiveType::SMALLINT: {
  Branch (598:9): [True: 0, False: 0]
599
0
            int16_t value = t_expr.int_literal.value;
600
0
            column->insert_data(reinterpret_cast<const char*>(&value), 0);
601
0
            break;
602
0
        }
603
0
        case TPrimitiveType::INT: {
  Branch (603:9): [True: 0, False: 0]
604
0
            int32_t value = t_expr.int_literal.value;
605
0
            column->insert_data(reinterpret_cast<const char*>(&value), 0);
606
0
            break;
607
0
        }
608
0
        default:
  Branch (608:9): [True: 0, False: 0]
609
0
            int64_t value = t_expr.int_literal.value;
610
0
            column->insert_data(reinterpret_cast<const char*>(&value), 0);
611
0
        }
612
0
        break;
613
0
    }
614
0
    case TExprNodeType::LARGE_INT_LITERAL: {
  Branch (614:5): [True: 0, False: 0]
615
0
        StringParser::ParseResult parse_result = StringParser::PARSE_SUCCESS;
616
0
        auto value = StringParser::string_to_int<__int128>(t_expr.large_int_literal.value.c_str(),
617
0
                                                           t_expr.large_int_literal.value.size(),
618
0
                                                           &parse_result);
619
0
        if (parse_result != StringParser::PARSE_SUCCESS) {
  Branch (619:13): [True: 0, False: 0]
620
0
            value = MAX_INT128;
621
0
        }
622
0
        column->insert_data(reinterpret_cast<const char*>(&value), 0);
623
0
        break;
624
0
    }
625
0
    case TExprNodeType::STRING_LITERAL: {
  Branch (625:5): [True: 0, False: 0]
626
0
        int len = t_expr.string_literal.value.size();
627
0
        const char* str_val = t_expr.string_literal.value.c_str();
628
0
        column->insert_data(str_val, len);
629
0
        break;
630
0
    }
631
0
    case TExprNodeType::BOOL_LITERAL: {
  Branch (631:5): [True: 0, False: 0]
632
0
        column->insert_data(reinterpret_cast<const char*>(&t_expr.bool_literal.value), 0);
633
0
        break;
634
0
    }
635
0
    case TExprNodeType::NULL_LITERAL: {
  Branch (635:5): [True: 0, False: 0]
636
        // insert a null literal
637
0
        if (!column->is_nullable()) {
  Branch (637:13): [True: 0, False: 0]
638
            // https://github.com/apache/doris/pull/39449 have forbid this cause. always add this check as protective measures
639
0
            return Status::InternalError("The column {} is not null, can't insert into NULL value.",
640
0
                                         part_key->first->get_by_position(pos).name);
641
0
        }
642
0
        column->insert_data(nullptr, 0);
643
0
        break;
644
0
    }
645
0
    default: {
  Branch (645:5): [True: 0, False: 0]
646
0
        return Status::InternalError("unsupported partition column node type, type={}",
647
0
                                     t_expr.node_type);
648
0
    }
649
0
    }
650
0
    part_key->second = column->size() - 1;
651
0
    return Status::OK();
652
0
}
653
// NOLINTEND(readability-function-size)
654
655
Status VOlapTablePartitionParam::_create_partition_keys(const std::vector<TExprNode>& t_exprs,
656
0
                                                        BlockRow* part_key) {
657
0
    for (int i = 0; i < t_exprs.size(); i++) {
  Branch (657:21): [True: 0, False: 0]
658
0
        RETURN_IF_ERROR(_create_partition_key(t_exprs[i], part_key, _partition_slot_locs[i]));
659
0
    }
660
0
    return Status::OK();
661
0
}
662
663
Status VOlapTablePartitionParam::generate_partition_from(const TOlapTablePartition& t_part,
664
0
                                                         VOlapTablePartition*& part_result) {
665
0
    DCHECK(part_result == nullptr);
666
    // here we set the default value of partition bounds first! if it doesn't have some key, it will be -1.
667
0
    part_result = _obj_pool.add(new VOlapTablePartition(&_partition_block));
668
0
    part_result->id = t_part.id;
669
0
    part_result->is_mutable = t_part.is_mutable;
670
    // only load_to_single_tablet = true will set load_tablet_idx
671
0
    if (t_part.__isset.load_tablet_idx) {
  Branch (671:9): [True: 0, False: 0]
672
0
        part_result->load_tablet_idx = t_part.load_tablet_idx;
673
0
    }
674
675
0
    if (_is_in_partition) {
  Branch (675:9): [True: 0, False: 0]
676
0
        for (const auto& keys : t_part.in_keys) {
  Branch (676:31): [True: 0, False: 0]
677
0
            RETURN_IF_ERROR(_create_partition_keys(
678
0
                    keys, &part_result->in_keys.emplace_back(&_partition_block, -1)));
679
0
        }
680
0
        if (t_part.__isset.is_default_partition && t_part.is_default_partition &&
  Branch (680:13): [True: 0, False: 0]
  Branch (680:52): [True: 0, False: 0]
681
0
            _default_partition == nullptr) {
  Branch (681:13): [True: 0, False: 0]
682
0
            _default_partition = part_result;
683
0
        }
684
0
    } else { // range
685
0
        if (t_part.__isset.start_keys) {
  Branch (685:13): [True: 0, False: 0]
686
0
            RETURN_IF_ERROR(_create_partition_keys(t_part.start_keys, &part_result->start_key));
687
0
        }
688
        // we generate the right bound but not insert into partition map
689
0
        if (t_part.__isset.end_keys) {
  Branch (689:13): [True: 0, False: 0]
690
0
            RETURN_IF_ERROR(_create_partition_keys(t_part.end_keys, &part_result->end_key));
691
0
        }
692
0
    }
693
694
0
    part_result->num_buckets = t_part.num_buckets;
695
0
    auto num_indexes = _schema->indexes().size();
696
0
    if (t_part.indexes.size() != num_indexes) {
  Branch (696:9): [True: 0, False: 0]
697
0
        return Status::InternalError(
698
0
                "number of partition's index is not equal with schema's"
699
0
                ", num_part_indexes={}, num_schema_indexes={}",
700
0
                t_part.indexes.size(), num_indexes);
701
0
    }
702
0
    part_result->indexes = t_part.indexes;
703
0
    std::sort(part_result->indexes.begin(), part_result->indexes.end(),
704
0
              [](const OlapTableIndexTablets& lhs, const OlapTableIndexTablets& rhs) {
705
0
                  return lhs.index_id < rhs.index_id;
706
0
              });
707
    // check index
708
0
    for (int j = 0; j < num_indexes; ++j) {
  Branch (708:21): [True: 0, False: 0]
709
0
        if (part_result->indexes[j].index_id != _schema->indexes()[j]->index_id) {
  Branch (709:13): [True: 0, False: 0]
710
0
            return Status::InternalError(
711
0
                    "partition's index is not equal with schema's"
712
0
                    ", part_index={}, schema_index={}",
713
0
                    part_result->indexes[j].index_id, _schema->indexes()[j]->index_id);
714
0
        }
715
0
    }
716
0
    if (t_part.__isset.total_replica_num) {
  Branch (716:9): [True: 0, False: 0]
717
0
        part_result->total_replica_num = t_part.total_replica_num;
718
0
    }
719
0
    if (t_part.__isset.load_required_replica_num) {
  Branch (719:9): [True: 0, False: 0]
720
0
        part_result->load_required_replica_num = t_part.load_required_replica_num;
721
0
    }
722
0
    return Status::OK();
723
0
}
724
725
Status VOlapTablePartitionParam::add_partitions(
726
0
        const std::vector<TOlapTablePartition>& partitions) {
727
0
    for (const auto& t_part : partitions) {
  Branch (727:29): [True: 0, False: 0]
728
0
        auto* part = _obj_pool.add(new VOlapTablePartition(&_partition_block));
729
0
        part->id = t_part.id;
730
0
        part->is_mutable = t_part.is_mutable;
731
732
        // we dont pass right keys when it's MAX_VALUE. so there's possibility we only have start_key but not end_key
733
        // range partition
734
0
        if (t_part.__isset.start_keys) {
  Branch (734:13): [True: 0, False: 0]
735
0
            RETURN_IF_ERROR(_create_partition_keys(t_part.start_keys, &part->start_key));
736
0
        }
737
0
        if (t_part.__isset.end_keys) {
  Branch (737:13): [True: 0, False: 0]
738
0
            RETURN_IF_ERROR(_create_partition_keys(t_part.end_keys, &part->end_key));
739
0
        }
740
        // list partition - we only set 1 value in 1 partition for new created ones
741
0
        if (t_part.__isset.in_keys) {
  Branch (741:13): [True: 0, False: 0]
742
0
            for (const auto& keys : t_part.in_keys) {
  Branch (742:35): [True: 0, False: 0]
743
0
                RETURN_IF_ERROR(_create_partition_keys(
744
0
                        keys, &part->in_keys.emplace_back(&_partition_block, -1)));
745
0
            }
746
0
            if (t_part.__isset.is_default_partition && t_part.is_default_partition) {
  Branch (746:17): [True: 0, False: 0]
  Branch (746:56): [True: 0, False: 0]
747
0
                _default_partition = part;
748
0
            }
749
0
        }
750
751
0
        part->num_buckets = t_part.num_buckets;
752
0
        auto num_indexes = _schema->indexes().size();
753
0
        if (t_part.indexes.size() != num_indexes) {
  Branch (753:13): [True: 0, False: 0]
754
0
            return Status::InternalError(
755
0
                    "number of partition's index is not equal with schema's"
756
0
                    ", num_part_indexes={}, num_schema_indexes={}",
757
0
                    t_part.indexes.size(), num_indexes);
758
0
        }
759
0
        part->indexes = t_part.indexes;
760
0
        std::sort(part->indexes.begin(), part->indexes.end(),
761
0
                  [](const OlapTableIndexTablets& lhs, const OlapTableIndexTablets& rhs) {
762
0
                      return lhs.index_id < rhs.index_id;
763
0
                  });
764
        // check index
765
0
        for (int j = 0; j < num_indexes; ++j) {
  Branch (765:25): [True: 0, False: 0]
766
0
            if (part->indexes[j].index_id != _schema->indexes()[j]->index_id) {
  Branch (766:17): [True: 0, False: 0]
767
0
                return Status::InternalError(
768
0
                        "partition's index is not equal with schema's"
769
0
                        ", part_index={}, schema_index={}",
770
0
                        part->indexes[j].index_id, _schema->indexes()[j]->index_id);
771
0
            }
772
0
        }
773
0
        _partitions.emplace_back(part);
774
        // after _creating_partiton_keys
775
0
        if (_is_in_partition) {
  Branch (775:13): [True: 0, False: 0]
776
0
            for (auto& in_key : part->in_keys) {
  Branch (776:31): [True: 0, False: 0]
777
0
                _partitions_map->emplace(std::tuple {in_key.first, in_key.second, false}, part);
778
0
            }
779
0
        } else {
780
0
            _partitions_map->emplace(std::tuple {part->end_key.first, part->end_key.second, false},
781
0
                                     part);
782
0
        }
783
0
    }
784
785
0
    return Status::OK();
786
0
}
787
788
Status VOlapTablePartitionParam::replace_partitions(
789
        std::vector<int64_t>& old_partition_ids,
790
0
        const std::vector<TOlapTablePartition>& new_partitions) {
791
    // remove old replaced partitions
792
0
    DCHECK(old_partition_ids.size() == new_partitions.size());
793
794
    // init and add new partitions. insert into _partitions
795
0
    for (int i = 0; i < new_partitions.size(); i++) {
  Branch (795:21): [True: 0, False: 0]
796
0
        const auto& t_part = new_partitions[i];
797
        // pair old_partition_ids and new_partitions one by one. TODO: sort to opt performance
798
0
        VOlapTablePartition* old_part = nullptr;
799
0
        auto old_part_id = old_partition_ids[i];
800
0
        if (auto it = std::find_if(
801
0
                    _partitions.begin(), _partitions.end(),
802
0
                    [=](const VOlapTablePartition* lhs) { return lhs->id == old_part_id; });
803
0
            it != _partitions.end()) {
  Branch (803:13): [True: 0, False: 0]
804
0
            old_part = *it;
805
0
        } else {
806
0
            return Status::InternalError("Cannot find old tablet {} in replacing", old_part_id);
807
0
        }
808
809
0
        auto* part = _obj_pool.add(new VOlapTablePartition(&_partition_block));
810
0
        part->id = t_part.id;
811
0
        part->is_mutable = t_part.is_mutable;
812
813
        /// just substitute directly. no need to remove and reinsert keys.
814
        // range partition
815
0
        part->start_key = std::move(old_part->start_key);
816
0
        part->end_key = std::move(old_part->end_key);
817
        // list partition
818
0
        part->in_keys = std::move(old_part->in_keys);
819
0
        if (t_part.__isset.is_default_partition && t_part.is_default_partition) {
  Branch (819:13): [True: 0, False: 0]
  Branch (819:52): [True: 0, False: 0]
820
0
            _default_partition = part;
821
0
        }
822
823
0
        part->num_buckets = t_part.num_buckets;
824
0
        auto num_indexes = _schema->indexes().size();
825
0
        if (t_part.indexes.size() != num_indexes) {
  Branch (825:13): [True: 0, False: 0]
826
0
            return Status::InternalError(
827
0
                    "number of partition's index is not equal with schema's"
828
0
                    ", num_part_indexes={}, num_schema_indexes={}",
829
0
                    t_part.indexes.size(), num_indexes);
830
0
        }
831
0
        part->indexes = t_part.indexes;
832
0
        std::sort(part->indexes.begin(), part->indexes.end(),
833
0
                  [](const OlapTableIndexTablets& lhs, const OlapTableIndexTablets& rhs) {
834
0
                      return lhs.index_id < rhs.index_id;
835
0
                  });
836
        // check index
837
0
        for (int j = 0; j < num_indexes; ++j) {
  Branch (837:25): [True: 0, False: 0]
838
0
            if (part->indexes[j].index_id != _schema->indexes()[j]->index_id) {
  Branch (838:17): [True: 0, False: 0]
839
0
                return Status::InternalError(
840
0
                        "partition's index is not equal with schema's"
841
0
                        ", part_index={}, schema_index={}",
842
0
                        part->indexes[j].index_id, _schema->indexes()[j]->index_id);
843
0
            }
844
0
        }
845
846
        // add new partitions with new id.
847
0
        _partitions.emplace_back(part);
848
0
        VLOG_NOTICE << "params add new partition " << part->id;
Line
Count
Source
42
0
#define VLOG_NOTICE VLOG(3)
849
850
        // replace items in _partition_maps
851
0
        if (_is_in_partition) {
  Branch (851:13): [True: 0, False: 0]
852
0
            for (auto& in_key : part->in_keys) {
  Branch (852:31): [True: 0, False: 0]
853
0
                (*_partitions_map)[std::tuple {in_key.first, in_key.second, false}] = part;
854
0
            }
855
0
        } else {
856
0
            (*_partitions_map)[std::tuple {part->end_key.first, part->end_key.second, false}] =
857
0
                    part;
858
0
        }
859
0
    }
860
    // remove old partitions by id
861
0
    std::ranges::sort(old_partition_ids);
862
0
    for (auto it = _partitions.begin(); it != _partitions.end();) {
  Branch (862:41): [True: 0, False: 0]
863
0
        if (std::ranges::binary_search(old_partition_ids, (*it)->id)) {
  Branch (863:13): [True: 0, False: 0]
864
0
            it = _partitions.erase(it);
865
0
        } else {
866
0
            it++;
867
0
        }
868
0
    }
869
870
0
    return Status::OK();
871
0
}
872
873
} // namespace doris