Coverage Report

Created: 2026-08-06 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
3.62k
        : _num_short_key_columns(schema.num_short_key_columns()) {
34
3.62k
    if (mow) {
35
278
        _init_mow(schema);
36
3.34k
    } else {
37
3.34k
        _init_non_mow(schema);
38
3.34k
    }
39
3.62k
}
40
41
278
void RowKeyEncoder::_init_mow(const TabletSchema& schema) {
42
    // encode the sequence id into the primary key index
43
278
    if (schema.has_sequence_col()) {
44
141
        const auto& column = schema.column(schema.sequence_col_idx());
45
141
        _seq_coder = get_key_coder(column.type());
46
141
        _seq_col_length = column.length();
47
141
    }
48
49
    // Which columns each view ends up holding:
50
    //
51
    //                     _sort_key_coders    _primary_key_coders
52
    //   no cluster key    key columns         key columns
53
    //   cluster keys      cluster key cols    key columns
54
    //
55
    // The primary key index is built on the schema key columns whatever the segment sorts by, so
56
    // every mow table gets that view, not just the ones with cluster keys. The sort-key view
57
    // follows the segment's own order, which is the only column set that differs between the two.
58
2.68k
    for (size_t cid = 0; cid < schema.num_key_columns(); ++cid) {
59
2.40k
        _primary_key_coders.push_back(get_key_coder(schema.column(cid).type()));
60
2.40k
    }
61
62
278
    if (schema.cluster_key_uids().empty()) {
63
254
        _add_default_sort_key_columns(schema);
64
254
        return;
65
254
    }
66
24
    _rowid_coder = get_key_coder(FieldType::OLAP_FIELD_TYPE_UNSIGNED_INT);
67
367
    for (auto uid : schema.cluster_key_uids()) {
68
367
        _add_sort_key_column(schema.column_by_uid(uid));
69
367
    }
70
24
}
71
72
3.34k
void RowKeyEncoder::_init_non_mow(const TabletSchema& schema) {
73
3.34k
    _add_default_sort_key_columns(schema);
74
3.34k
}
75
76
3.60k
void RowKeyEncoder::_add_default_sort_key_columns(const TabletSchema& schema) {
77
9.08k
    for (size_t cid = 0; cid < schema.num_key_columns(); ++cid) {
78
5.48k
        _add_sort_key_column(schema.column(cid));
79
5.48k
    }
80
3.60k
}
81
82
5.85k
void RowKeyEncoder::_add_sort_key_column(const TabletColumn& column) {
83
5.85k
    _sort_key_coders.push_back(get_key_coder(column.type()));
84
5.85k
    _sort_key_index_size.push_back(cast_set<uint16_t>(column.index_length()));
85
5.85k
}
86
87
std::string RowKeyEncoder::full_encode(const std::vector<IOlapColumnDataAccessor*>& key_columns,
88
12.4k
                                       size_t pos) const {
89
12.4k
    assert(_sort_key_index_size.size() == _sort_key_coders.size());
90
12.4k
    assert(key_columns.size() == _sort_key_coders.size());
91
12.4k
    return _full_encode(_sort_key_coders, key_columns, pos);
92
12.4k
}
93
94
std::string RowKeyEncoder::full_encode_primary_keys(
95
1.43k
        const std::vector<IOlapColumnDataAccessor*>& key_columns, size_t pos) const {
96
1.43k
    return _full_encode(_primary_key_coders, key_columns, pos);
97
1.43k
}
98
99
namespace {
100
// Shared row-key encoding base: for each key column, write a null marker for
101
// a null value, otherwise a normal marker followed by whatever `encode_field`
102
// appends. `encode_field(cid, field, out)` is the only thing that differs between
103
// the full key encode and the short-key prefix encode.
104
template <typename EncodeField>
105
std::string encode_key_columns(const std::vector<IOlapColumnDataAccessor*>& key_columns, size_t pos,
106
28.3k
                               EncodeField&& encode_field) {
107
28.3k
    std::string encoded_keys;
108
28.3k
    size_t cid = 0;
109
48.8k
    for (const auto& column : key_columns) {
110
48.8k
        const auto* field = column->get_data_at(pos);
111
48.8k
        if (UNLIKELY(!field)) {
112
1.41k
            encoded_keys.push_back(KeyConsts::KEY_NULL_FIRST_MARKER);
113
1.41k
            ++cid;
114
1.41k
            continue;
115
1.41k
        }
116
47.4k
        encoded_keys.push_back(KeyConsts::KEY_NORMAL_MARKER);
117
47.4k
        encode_field(cid, field, &encoded_keys);
118
47.4k
        ++cid;
119
47.4k
    }
120
28.3k
    return encoded_keys;
121
28.3k
}
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
106
13.8k
                               EncodeField&& encode_field) {
107
13.8k
    std::string encoded_keys;
108
13.8k
    size_t cid = 0;
109
30.6k
    for (const auto& column : key_columns) {
110
30.6k
        const auto* field = column->get_data_at(pos);
111
30.6k
        if (UNLIKELY(!field)) {
112
890
            encoded_keys.push_back(KeyConsts::KEY_NULL_FIRST_MARKER);
113
890
            ++cid;
114
890
            continue;
115
890
        }
116
29.7k
        encoded_keys.push_back(KeyConsts::KEY_NORMAL_MARKER);
117
29.7k
        encode_field(cid, field, &encoded_keys);
118
29.7k
        ++cid;
119
29.7k
    }
120
13.8k
    return encoded_keys;
121
13.8k
}
row_key_encoder.cpp:_ZN5doris12_GLOBAL__N_118encode_key_columnsIZNKS_13RowKeyEncoder17encode_short_keysB5cxx11ERKSt6vectorIPNS_23IOlapColumnDataAccessorESaIS5_EEmE3$_0EENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES9_mOT_
Line
Count
Source
106
14.5k
                               EncodeField&& encode_field) {
107
14.5k
    std::string encoded_keys;
108
14.5k
    size_t cid = 0;
109
18.1k
    for (const auto& column : key_columns) {
110
18.1k
        const auto* field = column->get_data_at(pos);
111
18.1k
        if (UNLIKELY(!field)) {
112
522
            encoded_keys.push_back(KeyConsts::KEY_NULL_FIRST_MARKER);
113
522
            ++cid;
114
522
            continue;
115
522
        }
116
17.6k
        encoded_keys.push_back(KeyConsts::KEY_NORMAL_MARKER);
117
17.6k
        encode_field(cid, field, &encoded_keys);
118
17.6k
        ++cid;
119
17.6k
    }
120
14.5k
    return encoded_keys;
121
14.5k
}
122
} // namespace
123
124
std::string RowKeyEncoder::_full_encode(const std::vector<const KeyCoder*>& key_coders,
125
                                        const std::vector<IOlapColumnDataAccessor*>& key_columns,
126
13.8k
                                        size_t pos) {
127
13.8k
    assert(key_columns.size() == key_coders.size());
128
13.8k
    return encode_key_columns(key_columns, pos,
129
29.7k
                              [&](size_t cid, const void* field, std::string* out) {
130
29.7k
                                  DCHECK(key_coders[cid] != nullptr);
131
29.7k
                                  key_coders[cid]->full_encode_ascending(field, out);
132
29.7k
                              });
133
13.8k
}
134
135
std::string RowKeyEncoder::encode_short_keys(
136
14.5k
        const std::vector<IOlapColumnDataAccessor*>& key_columns, size_t pos) const {
137
14.5k
    assert(key_columns.size() == _num_short_key_columns);
138
14.5k
    assert(key_columns.size() <= _sort_key_coders.size());
139
14.5k
    return encode_key_columns(
140
17.6k
            key_columns, pos, [&](size_t cid, const void* field, std::string* out) {
141
17.6k
                _sort_key_coders[cid]->encode_ascending(field, _sort_key_index_size[cid], out);
142
17.6k
            });
143
14.5k
}
144
145
void RowKeyEncoder::append_seq_suffix(std::string* encoded_keys,
146
424
                                      const IOlapColumnDataAccessor* seq_column, size_t pos) const {
147
424
    const auto* field = seq_column->get_data_at(pos);
148
    // So the primary key index can still use it, encode a null seq column as
149
    // the smallest value of its length.
150
424
    if (UNLIKELY(!field)) {
151
76
        encoded_keys->push_back(KeyConsts::KEY_NULL_FIRST_MARKER);
152
76
        encoded_keys->append(_seq_col_length, KeyConsts::KEY_MINIMAL_MARKER);
153
76
        return;
154
76
    }
155
348
    encoded_keys->push_back(KeyConsts::KEY_NORMAL_MARKER);
156
348
    _seq_coder->full_encode_ascending(field, encoded_keys);
157
348
}
158
159
166
void RowKeyEncoder::append_rowid_suffix(std::string* encoded_keys, uint32_t rowid) const {
160
166
    encoded_keys->push_back(KeyConsts::KEY_NORMAL_MARKER);
161
166
    _rowid_coder->full_encode_ascending(&rowid, encoded_keys);
162
166
}
163
164
} // namespace doris