Coverage Report

Created: 2026-07-27 20:25

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
be/src/storage/key/row_key_encoder.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 "storage/key/row_key_encoder.h"
19
20
#include <cassert>
21
22
#include "common/cast_set.h"
23
#include "common/compiler_util.h" // IWYU pragma: keep
24
#include "common/consts.h"
25
#include "common/logging.h"
26
#include "storage/iterator/olap_data_convertor.h"
27
#include "storage/key_coder.h"
28
#include "storage/tablet/tablet_schema.h"
29
30
namespace doris {
31
32
RowKeyEncoder::RowKeyEncoder(const TabletSchema& schema, bool mow)
33
5.23k
        : _num_short_key_columns(schema.num_short_key_columns()) {
34
5.23k
    if (mow) {
35
196
        _init_mow(schema);
36
5.03k
    } else {
37
5.03k
        _init_non_mow(schema);
38
5.03k
    }
39
5.23k
}
40
41
196
void RowKeyEncoder::_init_mow(const TabletSchema& schema) {
42
    // encode the sequence id into the primary key index
43
196
    if (schema.has_sequence_col()) {
44
84
        const auto& column = schema.column(schema.sequence_col_idx());
45
84
        _seq_coder = get_key_coder(column.type());
46
84
        _seq_col_length = column.length();
47
84
    }
48
49
196
    if (schema.cluster_key_uids().empty()) {
50
182
        _add_default_sort_key_columns(schema);
51
182
        return;
52
182
    }
53
54
94
    for (size_t cid = 0; cid < schema.num_key_columns(); ++cid) {
55
80
        _primary_key_coders.push_back(get_key_coder(schema.column(cid).type()));
56
80
    }
57
14
    _rowid_coder = get_key_coder(FieldType::OLAP_FIELD_TYPE_UNSIGNED_INT);
58
86
    for (auto uid : schema.cluster_key_uids()) {
59
86
        _add_sort_key_column(schema.column_by_uid(uid));
60
86
    }
61
14
}
62
63
5.03k
void RowKeyEncoder::_init_non_mow(const TabletSchema& schema) {
64
5.03k
    _add_default_sort_key_columns(schema);
65
5.03k
}
66
67
5.21k
void RowKeyEncoder::_add_default_sort_key_columns(const TabletSchema& schema) {
68
9.91k
    for (size_t cid = 0; cid < schema.num_key_columns(); ++cid) {
69
4.69k
        _add_sort_key_column(schema.column(cid));
70
4.69k
    }
71
5.21k
}
72
73
4.78k
void RowKeyEncoder::_add_sort_key_column(const TabletColumn& column) {
74
4.78k
    _sort_key_coders.push_back(get_key_coder(column.type()));
75
4.78k
    _sort_key_index_size.push_back(cast_set<uint16_t>(column.index_length()));
76
4.78k
}
77
78
std::string RowKeyEncoder::full_encode(const std::vector<IOlapColumnDataAccessor*>& key_columns,
79
14.7k
                                       size_t pos) const {
80
14.7k
    assert(_sort_key_index_size.size() == _sort_key_coders.size());
81
14.7k
    assert(key_columns.size() == _sort_key_coders.size());
82
14.7k
    return _full_encode(_sort_key_coders, key_columns, pos);
83
14.7k
}
84
85
std::string RowKeyEncoder::full_encode_primary_keys(
86
236
        const std::vector<IOlapColumnDataAccessor*>& key_columns, size_t pos) const {
87
236
    return _full_encode(_primary_key_coders, key_columns, pos);
88
236
}
89
90
namespace {
91
// Shared row-key encoding base: for each key column, write a null marker for
92
// a null value, otherwise a normal marker followed by whatever `encode_field`
93
// appends. `encode_field(cid, field, out)` is the only thing that differs between
94
// the full key encode and the short-key prefix encode.
95
template <typename EncodeField>
96
std::string encode_key_columns(const std::vector<IOlapColumnDataAccessor*>& key_columns, size_t pos,
97
42.1k
                               EncodeField&& encode_field) {
98
42.1k
    std::string encoded_keys;
99
42.1k
    size_t cid = 0;
100
62.7k
    for (const auto& column : key_columns) {
101
62.7k
        const auto* field = column->get_data_at(pos);
102
62.7k
        if (UNLIKELY(!field)) {
103
584
            encoded_keys.push_back(KeyConsts::KEY_NULL_FIRST_MARKER);
104
584
            ++cid;
105
584
            continue;
106
584
        }
107
62.2k
        encoded_keys.push_back(KeyConsts::KEY_NORMAL_MARKER);
108
62.2k
        encode_field(cid, field, &encoded_keys);
109
62.2k
        ++cid;
110
62.2k
    }
111
42.1k
    return encoded_keys;
112
42.1k
}
row_key_encoder.cpp:_ZN5doris12_GLOBAL__N_118encode_key_columnsIZNS_13RowKeyEncoder12_full_encodeB5cxx11ERKSt6vectorIPKNS_8KeyCoderESaIS6_EERKS3_IPNS_23IOlapColumnDataAccessorESaISC_EEmE3$_0EENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESG_mOT_
Line
Count
Source
97
14.9k
                               EncodeField&& encode_field) {
98
14.9k
    std::string encoded_keys;
99
14.9k
    size_t cid = 0;
100
29.8k
    for (const auto& column : key_columns) {
101
29.8k
        const auto* field = column->get_data_at(pos);
102
29.8k
        if (UNLIKELY(!field)) {
103
340
            encoded_keys.push_back(KeyConsts::KEY_NULL_FIRST_MARKER);
104
340
            ++cid;
105
340
            continue;
106
340
        }
107
29.5k
        encoded_keys.push_back(KeyConsts::KEY_NORMAL_MARKER);
108
29.5k
        encode_field(cid, field, &encoded_keys);
109
29.5k
        ++cid;
110
29.5k
    }
111
14.9k
    return encoded_keys;
112
14.9k
}
row_key_encoder.cpp:_ZN5doris12_GLOBAL__N_118encode_key_columnsIZNKS_13RowKeyEncoder17encode_short_keysB5cxx11ERKSt6vectorIPNS_23IOlapColumnDataAccessorESaIS5_EEmE3$_0EENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES9_mOT_
Line
Count
Source
97
27.1k
                               EncodeField&& encode_field) {
98
27.1k
    std::string encoded_keys;
99
27.1k
    size_t cid = 0;
100
32.9k
    for (const auto& column : key_columns) {
101
32.9k
        const auto* field = column->get_data_at(pos);
102
32.9k
        if (UNLIKELY(!field)) {
103
244
            encoded_keys.push_back(KeyConsts::KEY_NULL_FIRST_MARKER);
104
244
            ++cid;
105
244
            continue;
106
244
        }
107
32.6k
        encoded_keys.push_back(KeyConsts::KEY_NORMAL_MARKER);
108
32.6k
        encode_field(cid, field, &encoded_keys);
109
32.6k
        ++cid;
110
32.6k
    }
111
27.1k
    return encoded_keys;
112
27.1k
}
113
} // namespace
114
115
std::string RowKeyEncoder::_full_encode(const std::vector<const KeyCoder*>& key_coders,
116
                                        const std::vector<IOlapColumnDataAccessor*>& key_columns,
117
14.9k
                                        size_t pos) {
118
14.9k
    assert(key_columns.size() == key_coders.size());
119
14.9k
    return encode_key_columns(key_columns, pos,
120
29.5k
                              [&](size_t cid, const void* field, std::string* out) {
121
29.5k
                                  DCHECK(key_coders[cid] != nullptr);
122
29.5k
                                  key_coders[cid]->full_encode_ascending(field, out);
123
29.5k
                              });
124
14.9k
}
125
126
std::string RowKeyEncoder::encode_short_keys(
127
27.1k
        const std::vector<IOlapColumnDataAccessor*>& key_columns, size_t pos) const {
128
27.1k
    assert(key_columns.size() == _num_short_key_columns);
129
27.1k
    assert(key_columns.size() <= _sort_key_coders.size());
130
27.1k
    return encode_key_columns(
131
32.6k
            key_columns, pos, [&](size_t cid, const void* field, std::string* out) {
132
32.6k
                _sort_key_coders[cid]->encode_ascending(field, _sort_key_index_size[cid], out);
133
32.6k
            });
134
27.1k
}
135
136
void RowKeyEncoder::append_seq_suffix(std::string* encoded_keys,
137
282
                                      const IOlapColumnDataAccessor* seq_column, size_t pos) const {
138
282
    const auto* field = seq_column->get_data_at(pos);
139
    // So the primary key index can still use it, encode a null seq column as
140
    // the smallest value of its length.
141
282
    if (UNLIKELY(!field)) {
142
24
        encoded_keys->push_back(KeyConsts::KEY_NULL_FIRST_MARKER);
143
24
        encoded_keys->append(_seq_col_length, KeyConsts::KEY_MINIMAL_MARKER);
144
24
        return;
145
24
    }
146
258
    encoded_keys->push_back(KeyConsts::KEY_NORMAL_MARKER);
147
258
    _seq_coder->full_encode_ascending(field, encoded_keys);
148
258
}
149
150
236
void RowKeyEncoder::append_rowid_suffix(std::string* encoded_keys, uint32_t rowid) const {
151
236
    encoded_keys->push_back(KeyConsts::KEY_NORMAL_MARKER);
152
236
    _rowid_coder->full_encode_ascending(&rowid, encoded_keys);
153
236
}
154
155
} // namespace doris